def __init__(self, plate, filename, motorSpeed=MOTORSPEED, fps=FPS, mjd=None):
        """! A Scan

        @param[in] plate, int
        @param[in] filename, string
        @param[in] motorSpeed, float
        @param[in] fps, frames per second, float
        @param[in] mjd, mdj or None
        """
        self.plate = plate
        self.motorSpeed = motorSpeed
        self.fps = fps
        if os.path.exists(filename):
            raise RuntimeError("file %s already exists, specify another, or remove it"%filename)
        self.filename = filename
        self.thresh = None
        self.bias = None
        self.motor = None
        self.now = datetime.now()
        self.mjd = mjd if mjd is not None else self.now.mjd
        self.dataLines = [] # will hold SCANPIX lines to be written to a file
from twisted.internet import reactor

from sdss.utilities.astrodatetime import datetime

from .camera import Camera, sortDetections, IMGBASENAME, IMGEXTENSION, getScanParams, \
    pickleDetectionList, unpickleCentroids
# from .imgProcess import DetectedFiberList
from .motor import MotorController
from .fiberAssign import SlitheadSolver, FocalSurfaceSolver

from . import plt

MOTOR_IP = "139.229.101.114"
MOTOR_PORT = 15000
MJD = floor(datetime.now().mjd)
BASEDIR = os.path.join(os.path.expanduser("~"), "scan", "%i"%MJD)
if not os.path.exists(BASEDIR):
    os.makedirs(BASEDIR)
# check for existing scan directories

fiberslitposfile = os.path.join(os.getenv("PYMAPPER_DIR"), "etc", "fiberpos.dat")
tstart = None

# import cProfile, pstats, StringIO
# pr = cProfile.Profile()

"""
todo: add re-detect/re-solve options
"""