Index: c/sas/sascalc/file_converter/convert_bsl_thread.py
===================================================================
--- src/sas/sascalc/file_converter/convert_bsl_thread.py	(revision 0b1a677a6bec9b3b30979ce36e64645b3028908b)
+++ 	(revision )
@@ -1,94 +1,0 @@
-import os
-import wx
-from sas.sascalc.data_util.calcthread import CalcThread
-from sas.sascalc.dataloader.data_info import Data2D
-from sas.sascalc.file_converter.red2d_writer import Red2DWriter
-
-import sys
-
-if sys.platform.count("darwin") > 0:
-    import time
-    stime = time.time()
-
-    def clock():
-        return time.time() - stime
-
-    def sleep(t):
-        return time.sleep(t)
-else:
-    from time import clock
-    from time import sleep
-
-class ConvertBSLThread(CalcThread):
-
-    def __init__(self, xy, frame_data, out_file, frame_number=None,
-        updatefn=None, completefn=None):
-        CalcThread.__init__(self, updatefn=updatefn, completefn=completefn)
-        (self.x_data, self.y_data) = xy
-        self.frame_data = frame_data
-        self.frame_number = frame_number
-        self.frame_filename = ''
-        self.out_file = out_file
-
-    def compute(self):
-        try:
-            completed = self._convert_to_red2d()
-        except Exception as e:
-            self.ready()
-            self.update(exception=e)
-            self.complete(success=False)
-            return
-
-        self.complete(success=completed)
-
-    def isquit(self):
-        """Check for interrupts.  Should be called frequently to
-        provide user responsiveness.  Also yields to other running
-        threads, which is required for good performance on OS X."""
-
-        # # Only called from within the running thread so no need to lock
-        # if self._running and self.yieldtime > 0 \
-        #     and clock() > self._time_for_nap:
-        #     sleep(self.yieldtime)
-        #     self._time_for_nap = clock() + self.worktime
-        return self._interrupting
-
-    def _convert_to_red2d(self):
-        """
-        Writes Data2D objects to Red2D .dat files. If more than one frame is
-        provided, the frame number will be appended to the filename of each
-        file written.
-
-        :param filepath: The filepath to write to
-        :param x: The x column of the data
-        :param y: The y column of the data
-        :param frame_data: A dictionary of the form frame_number: data, where
-        data is a 2D numpy array containing the intensity data
-
-        :return: True if export completed, False if export cancelled by user
-        """
-        filename = os.path.split(self.out_file)[-1]
-        filepath = os.path.split(self.out_file)[0]
-        writer = Red2DWriter()
-
-        if self.isquit():
-            return False
-
-        if self.frame_number is not None:
-            frame_filename = filename.split('.')
-            frame_filename[0] += str(self.frame_number)
-            frame_filename = '.'.join(frame_filename)
-        else:
-            frame_filename = filename
-
-        self.ready()
-        self.update(msg="Writing file: {}".format(frame_filename))
-        data_i = self.frame_data.reshape((len(self.x_data),1))
-        data_info = Data2D(data=data_i, qx_data=self.x_data, qy_data=self.y_data)
-        success = writer.write(os.path.join(filepath, frame_filename), data_info, self)
-
-        # Used by ConverterPanel.conversion_complete to notify user that file
-        # has been written (or that there was an error)
-        self.frame_filename = frame_filename
-
-        return success
Index: src/sas/sasgui/perspectives/file_converter/converter_panel.py
===================================================================
--- src/sas/sasgui/perspectives/file_converter/converter_panel.py	(revision 254f08879892804e617ce1b05ddc17ca6275f655)
+++ src/sas/sasgui/perspectives/file_converter/converter_panel.py	(revision e9e777c93df483ed7924377c0c83b739ecdd6241)
@@ -19,9 +19,10 @@
 from sas.sasgui.guiframe.documentation_window import DocumentationWindow
 from sas.sasgui.guiframe.dataFitting import Data1D
+from sas.sascalc.dataloader.data_info import Data2D
 from sas.sasgui.guiframe.utils import check_float
 from sas.sascalc.file_converter.cansas_writer import CansasWriter
 from sas.sascalc.file_converter.otoko_loader import OTOKOLoader
 from sas.sascalc.file_converter.bsl_loader import BSLLoader
-from sas.sascalc.file_converter.convert_bsl_thread import ConvertBSLThread
+from sas.sascalc.file_converter.nxcansas_writer import NXcanSASWriter
 from sas.sascalc.dataloader.data_info import Detector
 from sas.sascalc.dataloader.data_info import Sample
@@ -57,6 +58,4 @@
         self.parent = parent
         self.meta_frames = []
-        self.to_convert = {}
-        self.bsl_thread = None
 
         # GUI inputs
@@ -233,12 +232,10 @@
             frame_data[frame] = loader.load_data()
 
-        # TODO: Tidy this up
         # Prepare axes values (arbitrary scale)
-        x_data = []
-        y_data = range(loader.n_pixels) * loader.n_rasters
-        for i in range(loader.n_rasters):
-            x_data += [i] * loader.n_pixels
-
-        return x_data, y_data, frame_data
+        x_data = loader.n_rasters * range(1,loader.n_pixels+1)
+        y_data = [loader.n_pixels * [i] for i in range(1, loader.n_rasters+1)]
+        y_data = np.reshape(y_data, (1, loader.n_pixels*loader.n_rasters))[0]
+
+        return (x_data, y_data), (loader.n_rasters, loader.n_pixels), frame_data
 
     def ask_frame_range(self, n_frames):
@@ -293,9 +290,4 @@
             return
 
-        if self.bsl_thread is not None and self.bsl_thread.isrunning():
-            self.to_convert = {}
-            self.bsl_thread.stop()
-            return
-
         self.sample.ID = self.title
 
@@ -308,19 +300,21 @@
             else: # self.data_type == 'bsl'
 
-                x, y, frame_data = self.extract_bsl_data(self.iq_input.GetPath())
+                (x, y), dimensions, frame_data = \
+                    self.extract_bsl_data(self.iq_input.GetPath())
                 if x == None and y == None and frame_data == None:
                     # Cancelled by user
                     return
 
-                self.to_convert = frame_data
-
-                frame_number, data = self.to_convert.popitem()
-                self.bsl_thread = ConvertBSLThread((x, y), data,
-                    self.output.GetPath(), frame_number=frame_number,
-                    updatefn=self.conversion_update,
-                    completefn=self.conversion_complete)
-                self.bsl_thread.queue()
-
-                self.convert_btn.SetLabel("Stop Conversion")
+                dataset = []
+                for i_data in frame_data.values():
+                    i_data = np.reshape(i_data, (1, i_data.size))[0]
+                    data2d = Data2D(data=i_data, qx_data=x, qy_data=y)
+                    dataset.append(data2d)
+                w = NXcanSASWriter()
+                dimensions = [dimensions] * len(dataset)
+                w.write(dataset, self.output.GetPath(), dimensions=dimensions)
+
+                wx.PostEvent(self.parent.manager.parent,
+                    StatusEvent(status="Conversion completed."))
                 return
 
@@ -389,35 +383,4 @@
             StatusEvent(status="Conversion completed."))
 
-    def conversion_update(self, msg="", exception=None):
-        if exception is not None:
-            msg = str(exception)
-            wx.PostEvent(self.parent.manager.parent,
-                StatusEvent(status=msg, info='error'))
-        else:
-            wx.PostEvent(self.parent.manager.parent,
-                StatusEvent(status=msg))
-
-    def conversion_complete(self, success=True):
-        msg = "Conversion of {} ".format(self.bsl_thread.frame_filename)
-
-        if success:
-            msg += "completed"
-        else:
-            msg += "failed"
-        wx.PostEvent(self.parent.manager.parent,
-            StatusEvent(status=msg))
-
-        if len(self.to_convert) == 0:
-            self.convert_btn.SetLabel("Convert")
-            self.bsl_thread = None
-            wx.PostEvent(self.parent.manager.parent,
-                StatusEvent(status="Conversion finished"))
-        else:
-            n, data = self.to_convert.popitem()
-            self.bsl_thread.frame_data = data
-            self.bsl_thread.frame_number = n
-            self.bsl_thread.queue()
-
-
     def on_help(self, event):
         """
@@ -511,5 +474,5 @@
             self.on_collapsible_pane(None)
             self.metadata_section.Disable()
-            self.output.SetWildcard("IGOR/DAT 2D file in Q_map (*.dat)|*.DAT")
+            self.output.SetWildcard("NXcanSAS HDF5 File (*.h5)|*.h5")
         else:
             self.q_input.Enable()
@@ -693,7 +656,4 @@
 
     def on_close(self, event):
-        if self.panel.bsl_thread is not None \
-            and self.panel.bsl_thread.isrunning():
-            self.panel.bsl_thread.stop()
         if self.manager is not None:
             self.manager.converter_frame = None
