Created
November 5, 2016 20:17
-
-
Save dmsnell/7bc0c0e14ea05368ed534c2aa5b41f4c to your computer and use it in GitHub Desktop.
Generate a star composite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const childProcess = require( 'child_process' ) | |
const fs = require( 'fs' ) | |
const spawn = childProcess.spawn | |
const spawnSync = childProcess.spawnSync | |
const l = m => { console.log( m ); return m } | |
const needsDir = dir => ! fs.existsSync( dir ) && fs.mkdirSync( dir ) | |
// "mw-tsdm-12.tif" -> 12 | |
const imageIndex = filename => | |
filename | |
.split( '-' )[2] | |
.split( '.' ) | |
.shift() | |
const getImages = () => { | |
const response = spawnSync( 'ls', [ 'src_tif' ], { encoding: 'utf-8' } ) | |
return response | |
.stdout | |
.trim() | |
.split( "\n" ) | |
.sort( ( a, b ) => imageIndex( a ) - imageIndex( b ) ) | |
} | |
const resizeForTesting = ( folder, images, next ) => { | |
const newBase = './small/' | |
l( 'resizing for testing' ) | |
needsDir( newBase ) | |
images.forEach( image => { | |
if ( fs.existsSync( `${ newBase }${ image }` ) ) { | |
return l( `${ image } already exists, skipping` ) | |
} | |
spawnSync( 'convert', [ | |
`${ folder }/${ image }`, | |
'-resize', '640x', | |
`${ newBase }${ image }` | |
] ) | |
} ) | |
next[0]( newBase, images, next.slice( 1 ) ) | |
} | |
const isolateStars = mask => ( folder, images, next ) => { | |
const newBase = './only-stars/' | |
l( 'Isolating the stars' ) | |
needsDir( newBase ) | |
images.forEach( image => { | |
if ( fs.existsSync( `${ newBase }${ image }` ) ) { | |
return l( `\talready isolated ${ image }`) | |
} | |
spawnSync( 'convert', [ | |
mask, | |
`${ folder }${ image }`, | |
'-evaluate-sequence', 'subtract', | |
`${ newBase }${ image }` | |
] ) | |
} ) | |
next[0]( newBase, images, next.slice( 1 ) ) | |
} | |
const convertToFits = ( folder, images, next = l ) => { | |
const newBase = './fits/' | |
l( 'converting to FITS' ) | |
needsDir( newBase ) | |
images.forEach( image => { | |
if ( fs.existsSync( `${ newBase }${ image.replace( /\.tif$/, '_1.fits' ) }` ) ) { | |
return l( `${ image.replace( /\.tif$/, '_1.fits' ) } already exists, skipping` ) | |
} | |
spawnSync( 'convert', [ | |
`${ folder }/${ image }`, | |
'-channel', 'rgb', | |
'-separate', | |
`${ newBase }${ image.replace( /\.tif$/, '_%d.fits') }` | |
] ) | |
} ) | |
next[0]( newBase, images, next.slice( 1 ) ) | |
} | |
const identifyAlignment = ( folder, images, next ) => { | |
const newBase = './identifications/' | |
const anchor = images[ Math.floor( images.length / 2 ) ] | |
l( 'identifying alignment' ) | |
needsDir( newBase ) | |
images.forEach( image => { | |
if ( fs.existsSync( `${ newBase }identifications-${ image }.pickle` ) ) { | |
return l( `identifications for ${ image } already exist, skipping` ) | |
} | |
spawnSync( 'rm', [ | |
'identifications.pickle' | |
] ) | |
spawnSync( 'python', [ | |
'astro_align.py', | |
'--identify-only', | |
'-r', `${ folder }${ anchor.replace( /\.tif$/, '_1.fits' ) }`, | |
`${ folder }${ image.replace( /\.tif$/, '_1.fits' ) }` | |
] ) | |
spawnSync( 'cp', [ | |
'./identifications.pickle', | |
`${ newBase }identifications-${ image }.pickle` | |
] ) | |
l( `\tidentified alignment for ${ image }` ) | |
} ) | |
next[0]( newBase, images, next.slice( 1 ) ) | |
} | |
const alignImages = ( folder, images, next ) => { | |
const newBase = './alipy_out/' | |
const anchor = images[ Math.floor( images.length / 2 ) ] | |
l( 'aligning to anchor' ) | |
needsDir( newBase ) | |
images.forEach( image => { | |
if ( | |
fs.existsSync( `${ newBase }${ image.replace( /\.tif$/, '_0_affineremap.fits' ) }` ) | |
&& | |
fs.existsSync( `${ newBase }${ image.replace( /\.tif$/, '_1_affineremap.fits' ) }` ) | |
&& | |
fs.existsSync( `${ newBase }${ image.replace( /\.tif$/, '_2_affineremap.fits' ) }` ) | |
) { | |
return l( `${ image } already exists, skipping` ) | |
} | |
spawnSync( 'python', [ | |
'astro_align.py', | |
'-i', `./identifications/identifications-${ image }.pickle` | |
] ) | |
l( `\taligned ${ image } to anchor`) | |
} ) | |
next[0]( newBase, images, next.slice( 1 ) ) | |
} | |
const copyOriginals = source => ( folder, images, next ) => { | |
const newBase = './only-stars/' | |
l( 'copying originals over no-stars' ) | |
spawnSync( 'rm', [ | |
'-rf', newBase | |
] ) | |
needsDir( newBase ) | |
spawnSync( 'cp', [ | |
'-R', source, newBase | |
] ) | |
l( 'originals copied' ) | |
next[0]( folder, images, next.slice( 1 ) ) | |
} | |
const combineFits = ( folder, images, next ) => { | |
const newBase = './rgb/' | |
l( 'combining FITS' ) | |
if ( ! fs.existsSync( newBase ) ) { | |
fs.mkdirSync( newBase ) | |
} | |
images.forEach( image => { | |
if ( fs.existsSync( `${ newBase }${ image }` ) ) { | |
return l( `${ image } already exists, skipping` ) | |
} | |
spawnSync( 'convert', [ | |
`${ folder }${ image.replace( /\.tif$/, '_0_affineremap.fits' ) }`, | |
`${ folder }${ image.replace( /\.tif$/, '_1_affineremap.fits' ) }`, | |
`${ folder }${ image.replace( /\.tif$/, '_2_affineremap.fits' ) }`, | |
'-combine', 'rgb', | |
`${ newBase }${ image }` | |
] ) | |
} ) | |
next[0]( newBase, images, next.slice( 1 ) ) | |
} | |
const sumImages = ( folder, images, next ) => { | |
const newBase = './groups/' | |
const N = 4 | |
const nextGroups = [] | |
l( 'adding into groups' ) | |
if ( ! fs.existsSync( newBase ) ) { | |
fs.mkdirSync( newBase ) | |
} | |
// split into groups | |
const grouper = ( [ groups, images ] ) => | |
images.length < N | |
? groups | |
: grouper( [ groups.concat( [ images.slice( 0, N ) ] ), images.slice( N ) ] ) | |
const groups = grouper( [ [], images ] ) | |
groups.forEach( ( group, i ) => { | |
if ( fs.existsSync( `${ newBase }group-${ i }.tif` ) ) { | |
nextGroups.push( i ) | |
return l( `group-${ i } already exists, skipping` ) | |
} | |
spawnSync( 'convert', [ | |
...group.map( f => `${ folder }${ f }` ), | |
'-evaluate-sequence', 'add', | |
'-depth', '32', | |
`${ newBase }group-${ i }.tif` | |
] ) | |
nextGroups.push( i ) | |
} ) | |
next[0]( newBase, nextGroups.map( i => `group-${ i }.tif` ), next.slice( 1 ) ) | |
} | |
const denoiseMedian = ( folder, images, next ) => { | |
l( 'denoising with median' ) | |
spawnSync( 'convert', l( [ | |
...images.map( f => `${ folder }${ f }` ), | |
'-evaluate-sequence', 'median', | |
'median-result.tif' | |
] ) ) | |
next[0]( '.', [ 'median-result.tif' ], next.slice( 1 ) ) | |
} | |
const finish = ( folder, images ) => { | |
l( 'done' ) | |
} | |
const main = () => { | |
const images = getImages() | |
const start = ( folder, images, next ) => next[0]( folder, images, next.slice(1) ) | |
start( './src_tif/', images, [ | |
resizeForTesting, | |
isolateStars( './coarse-mask.tif' ), | |
convertToFits, | |
identifyAlignment, | |
copyOriginals( './src_tif/' ), | |
alignImages, | |
combineFits, | |
sumImages, | |
denoiseMedian, | |
finish | |
] ) | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment