def save_to_igor_itx(file_path: str,
                     xs: List[np.ndarray],
                     datas: List[np.ndarray],
                     names: List[str],
                     ys: Optional[List[np.ndarray]] = None,
                     x_labels: Optional[Union[str, List[str]]] = None,
                     y_labels: Optional[Union[str, List[str]]] = None):
    """Save data to a .itx file which can be dropped into Igor"""
    def check_axis_linear(arr: np.ndarray, axis: str, name: str,
                          current_waves: list) -> bool:
        if arr.shape[-1] > 1 and not np.all(
                np.isclose(np.diff(arr),
                           np.diff(arr)[0])):
            logger.warning(
                f"{file_path}: Igor doesn't support a non-linear {axis}-axis. Saving as separate wave"
            )
            axis_wave = IgorWave(arr, name=name + f'_{axis}')
            current_waves.append(axis_wave)
            return False
        else:
            return True

    if x_labels is None or isinstance(x_labels, str):
        x_labels = [x_labels] * len(datas)
    if y_labels is None or isinstance(y_labels, str):
        y_labels = [y_labels] * len(datas)
    if ys is None:
        ys = [None] * len(datas)
    assert all([
        len(datas) == len(list_) for list_ in [xs, names, x_labels, y_labels]
    ])

    waves = []
    for x, y, data, name, x_label, y_label in zip(xs, ys, datas, names,
                                                  x_labels, y_labels):
        wave = IgorWave(data, name=name)
        if x is not None:
            if check_axis_linear(x, 'x', name, waves):
                wave.set_dimscale('x',
                                  x[0],
                                  np.mean(np.diff(x)),
                                  units=x_label)
        if y is not None:
            if check_axis_linear(y, 'y', name, waves):
                wave.set_dimscale('y',
                                  y[0],
                                  np.mean(np.diff(y)),
                                  units=y_label)
        elif y_label is not None:
            wave.set_datascale(y_label)
        waves.append(wave)

    with open(file_path, 'w') as fp:
        for wave in waves:
            wave.save_itx(
                fp, image=True
            )  # Image = True hopefully makes np and igor match in x/y
Beispiel #2
0
 def test_data_units(self):
     wavename = 'wave0'
     unitslist = ('', 'sec', 'second')
     descs = ('empty units', 'short units', 'long units')
     for desc, units in zip(descs, unitslist):
         with self.subTest(desc):
             com = 'X SetScale d,.*"%s",.*\'%s\'' % (units, wavename)
             array = np.random.randint(0, 100, 10, dtype=np.int32)
             wave = IgorWave(array)
             wave.set_datascale(units)
             with TemporaryFile('wb') as fp:
                 wave.save(fp)
             with TemporaryFile('w+t') as fp:
                 wave.save_itx(fp)
                 fp.seek(0)
                 content = fp.read()
                 self.assertRegex(content, com)
def fig_to_igor_itx(f: go.Figure, filepath: str):
    d = data_from_plotly_fig(f)
    waves = []
    for k in d:
        if not k.endswith('_x') and not k.endswith('_y'):
            wave = IgorWave(d[k], name=k)
            wave.set_datascale(f.layout.yaxis.title.text)
            for dim in ['x', 'y']:
                if f'{k}_{dim}' in d:
                    dim_arr = d[f'{k}_{dim}']
                    wave.set_dimscale('x',
                                      dim_arr[0],
                                      np.mean(np.diff(dim_arr)),
                                      units=f.layout.xaxis.title.text)
            waves.append(wave)
    with open(filepath, 'w') as fp:
        for wave in waves:
            wave.save_itx(
                fp, image=True
            )  # Image = True hopefully makes np and igor match in x/y