

#Calculation of harmonic distortion using Fourier transform,
#here from the following two types of text files (txt or csv):
#
#
# 1a)Text file from the Hantek DSO4102C oscilloscope and other oscilloscopes
#    or files created in other ways, whose output file begins as follows:
%
%      #timebase=400000000(ps)
%      ,#voltbase=1000000(mv/100)
%      #size=20064
%      1.00E-06,-2.560
%      2.00E-06,-2.560
%      lines with numbers continues and have the same syntax until end of file
%
#    Note: Since octave also uses hash (#) symbol for comments, and first
#      three lines of file begin with this symbol, I have used percent sign (%)
#      to mark the beginning of file for comments. In file, these lines begin
#      with symbols # and ,# or with numbers, and do not contain any percent
#      signs with spaces at the beginning.
#
#    Here, the program assumes ONLY ONE channel recording!!
#
#    For files from Hantek DSO4102C oscilloscope, program assumes that
#    they ALWAYS contain only ONE channel recording, even though oscilloscope
#    can record up to two (or up to four for a slightly different type)
#    channels.  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#
#    At the beginning of file, there are three lines beginning with
#    characters # and ,# which have different values. I am (currently) only
#    using second one, beginning with ,#voltbase=...  This is vertical range
#    of oscilloscope (i.e., across entire screen), and after multiplying
#    by 1e-5, it is in volts (in file, it is in hundredths of millivolt).
#
#    Following lines contains data, and there are two lines as an example here.
#    In file, they are located after spaces with % indicating notes,
#    i.e., they begin with digits. Value separator is a comma, and decimal
#    separator is a dot. First number is sampling time from the start
#    [in seconds], and second number (after comma) is measured value.
#
#    Note on sampling times: since output to the file on Hantek DSO4102C
#      oscilloscope was probably done by some clowns or novices or who knows
#      who, they only did it to 3 valid digits, which is nonsense, because
#      in that exponential form, those 3 digits will soon be filled up and
#      then a bunch of values will have the same time, so graph drawn from
#      it is also nonsense !!!!!!
#      To eliminate this, I calculate interval from the first two times
#      (it's still okay there, but I don't know what would happen if interval
#      was greater than significant 3 digits - it would have to be expressed
#      in more digits than 3, and I don't know if that's possible) and with
#      calculated interval, I calculate times from first time again and
#      use the calculated times instead of times read from file.
#
#      Or if someone edited a file from an oscilloscope in Notepad or similar,
#      trimming the beginning to where above-described limitation occurs,
#      then program would not calculate the timing correctly: if first two
#      time values are the same, program will incorrectly calculate sampling
#      interval (it will be = 0), and that would be big laugh !!!!!!
#
#
#
# 1b)A text file generated by another program based on Hantek DSO4102C
#    oscilloscope files, e.g., with a calculated signal for program testing.
#    Such a file begins, for example, as follows:
%
%      #timebase=19000000000(ps)
%      ,#voltbase=2.5(V); is simulated resolution of 12bit AD converter from range ±10V
%      #size=19000
%      0,0.002442
%      1E-06,0.01709
%      2E-06,0.03175
%      lines with numbers continues and have the same syntax until end of file
%
#    or like this:
%
%      #timebase=1000000000(ps)
%      ,#voltbase=10(V); it is simulated by calculation with maximum possible accuracy of simulation program.
%      #size=19000
%      0,0
%      5.26315789473684E-08,0.00330693957508402
%      1.05263157894737E-07,0.0066138787885261
%      lines with numbers continues and have the same syntax until end of file
%
#    Notes on example are the same as in point 1a), and there may also
#    be only ONE channel here.
#
#    File contains three lines beginning with characters # and ,# similar
#    to point 1a), difference being in the text added after semicolon
#    in second line. I created a program for generating such a file in
#    MS Visual Studio, which adds text automatically.
#
#    Program searches for a simulation by keyword "simulated" (without
#    quotation marks) in second line, and therefore, if it is a signal that
#    is not measured by an oscilloscope but generated in another way, this
#    word MUST be there, and then program assumes that it is a simulation.
#
#    There are two examples of simulation here:
#    - first, where keyword is followed by text containing two numbers:
#         first defines how many bits calculated signal is quantized (divided)
#         into, i.e., what simulated resolution of the AD (analog-to-digital)
#         converter is, and second number indicates range from which it
#         is quantized (the range of the AD converter). Program reads these
#         two numbers in the order given in example (their order is a condition
#         for correct determination) from file and writes them to the output.
#         As can be seen in example, first recorded signal value is not zero,
#         and values are recorded with fewer valid digits than in second
#         example, because in this case a resolution of 12 bits was simulated,
#         i.e., the AD converter range is divided into 4096 levels.
#         Note: With frequently used 8-bit resolution of AD converters
#               in cheaper oscilloscopes, signal has only 256 levels.
#
#    - second, where there is no number after the keyword, and therefore
#         program assumes that it is purely a calculated signal at maximum
#         accuracy of program that calculated it. Maximum accuracy can also
#         be seen in number of digits to which values are written.
#
#
#
#
# 2) Text file from OWON ADS800/900 series oscilloscopes and other
#    oscilloscopes or files created in other ways, whose output file
#    begins as follows:
%
%      Model,ADS802A
%      Firmware Version,V1.0.1.7.1
%
%      Horizontal Units,s
%      TimeBase,0.0000100
%      Horizontal,0.0
%      Sample Interval,2.0E-7
%      Record Length,100000
%
%      Channel,CH1,CH2
%      Probe attenuation,1.0X,1.0X
%      Vertical Offset,0.00div,0.00div
%      vertical Scale,50.00mV,100.0mV
%      Label,?,?
%      Frequency,1.000kHz,872.7Hz
%      Period,1.000ms,1.145ms
%      PK-PK,316.5mV,409.0mV
%      Average,335.9μV,375.0μV
%      Vertical pos,0,0
%      Per ADC value,50.000000,100.000000
%
%      TIME(Units:s),CH1(Units:V),CH2(Units:V),
%      -0.0100000,0.003,-0.003
%      -0.0099998,0.004,-0.003
%      -0.0099996,0.003,-0.003
%      -0.0099994,0.002,-0.006
%      lines with numbers continues and have the same syntax until end of file
%
#    Note: Here, I have again used the % character for comments at beginning
#      of file. In file, lines begin with text or numbers and do not contain
#      any % characters with spaces at beginning.
#
#    I can only assume that program is compatible with entire ADS 800/900
#    series, as I have an ADS802A oscilloscope and have not (yet) had
#    opportunity to test files from other oscilloscopes in this series,
#    but hopefully they will be the same.
#
#    There can be one to ten channels here, although this type of oscilloscope
#    can have a maximum of four analog channels. Program assumes that data
#    is saved to file as "Wave" type and that any combination of channels has
#    been set as the source, but NOT MATH, DIR, and FFT types, which I have
#    not tried yet. Example shows a file with two channels.
#
#    At beginning, file contains 22 lines of text describing type and settings
#    and some measured values of oscilloscope, the meaning of which is quite
#    clear from file. I (so far) only use values "Channel,..." which is
#    identification of recorded channels, "Model," which is model of
#    oscilloscope, "(Units:" followed by units for individual recorded data,
#    and "vertical Scale,...", which is set vertical sensitivity of oscilloscope
#    in these units per 1 vertical div of screen, and since screen has a total
#    of 8 divs vertically, I multiply this value by 8 and enter it in output
#    of OWON oscilloscope program as oscilloscope range.
#
#    Following lines look like this (there are four examples here, and again
#    in file they are after the % symbols indicating comments, i.e., they
#    start with numbers): value separator is a comma, and decimal separator
#    is a dot. First number is time from start [in seconds] and second and any
#    subsequent numbers (after the comma) are measured values of individual
#    channels.
#
#    Because oscilloscope allows multiple channels to be written to a file
#    in form of additional values added to each line (ADS802A/ADS812A/ADS822A
#    are dual-channel and ADS804A ADS814A ADS824A are quad-channel), if program
#    detects more channels in file, it will ask which one to process, and that
#    channel will be processed further.
#
#
#    Note on WRITING TO .CSV FILES: When I wrote something about clowns and
#      the like in relation to HANTEK oscilloscope, I don't know what to call
#      it here, because there were far greater problems with writing to these
#      files (but also to .zip and .mat) that I complained about, namely that
#      after delivery, oscilloscope only recorded first 2047 data points
#      correctly in these files (times were correct throughout entire range),
#      and then there were almost constant random values (constant in the sense
#      of file in question, in another file there were different ones). This
#      meant that ONLY recording in the shortest file with 1000 values was
#      "usable" because it simply "fit" into this number; longer files only
#      had the first 2047 data points "usable," which was useless to me.
#      So, about a week after delivery (i.e., November 17, 2025), I complained
#      about problem in two places (in China, because I bought the oscilloscope
#      from Banggood):
#
#       1) directly from Owon (although I didn't buy it there, but what if...)
#          at general address from their website:
#              info@owon.com.cn
#          however, as I expected, there was absolutely NO response...
#          (i.e., until February 6, 2026).
#
#       2) at Banggood on the page where I bought the oscilloscope, after
#          logging into my account with them, of course:
#              https://www.banggood.com/cs/...
#          and here the approach was quite accommodating. Basically, if
#          I disregard some specifics of the people and settings of their
#          website, thanks to their company, I received a working upgrade after
#          more than a month (December 24, 2025). The most important
#          "peculiarity" is that customer MUST take some action within 7 DAYS,
#          and if they don't (as in my case, when I was waiting for their
#          response even though they wrote that I should wait until they
#          sentupgrade and that it would take a while), they CLOSE
#          CONVERSATION...  Admittedly, my oscilloscope had firmware version
#          V1.0.1.0.17 when I bought it (with CSV writing not working), and in
#          the first round they sent me an upgrade to version V1.0.1.7.1, which
#          I was unable to install immediately due to incorrect naming of sent
#          file (as soon as I received file, I tried to install it, oscilloscope
#          recognized upgrade, but after launching it, oscilloscope reported
#          a "Parse error"). And when I renamed it and successfully installed
#          it, the CSV writing still did not work... Finally, Banggood sent
#          me email address of a lady from OWON (I don't know if I can give
#          it here), and on December 11, 2025, I sent her a description of
#          problem again. She replied (on December 16, 2025), although not
#          immediately after I sent email, saying that she would look into
#          it and that I would have to wait. Well, then on December 24, 2025,
#          she sent me (as a gift??) an upgrade to version V1.0.1.7.2,
#          and it WORKS, hooray... (although it still has some "bugs"; for
#          example, as can be seen from the above excerpt from the beginning
#          of CSV file, it still proudly displays firmware version V1.0.1.7.1
#          and not V1.0.1.7.2, which was uploaded...)
#
#
#
#  Oscilloscope type is determined ONLY by number of text lines at beginning
#  of file, partly because HANTEK oscilloscope does not list any model such
#  as OWON there, so I hope that any upgrade of oscilloscope will not affect
#  this, but given that in the entire time I have had HANTEK oscilloscope
#  (about 5 years), I have not seen any upgrades for it anywhere, and given
#  above-described difficulties with recording to a csv file with OWON
#  oscilloscope, I do not expect any upgrades to be available for either of
#  them in the future.
#
#  Program contains all necessary functions within itself, so it does not call
#  any functions stored in other *.m files.
#
#  For its operation, it needs to have signal package installed because it uses
#  some of its functions. I have package, i.e., "signal-1.4.6.tar.gz" file,
#  downloaded from:
#          https://gnu-octave.github.io/packages/signal/
#
#  I started developing program in Octave version 10.2.0, i.e. GNU Octave,
#  which is available at:
#          https://octave.org/
#  it was tested and completed (so far) in February 2026 in Octave version
#  10.3.0. According to my testing, it is NOT compatible with MATLAB,
#  there are quite a few differences...
#
#
#
global VerzeProg;
VerzeProg = '19 February 2026';  ###  Luděk Ruffer        lruffer@volny.cz








# If there is no semicolon at end of command, Octave will also display output
# in the command window!!!


# Note from NUF: In order for file to open via UIgetfile, you need to go to
#    main menu of Octave and select: EDIT/Preferences and then check
#    Use native file dialogs in the General tab. Otherwise, loading non-default
#    directories takes a long time.





pkg load signal;      #Without loading package Signal, neither Help nor
                      #its contents are accessible in Octave, so in order
                      #to access it, this program must be run at least once....

close all;            #erases all figures
clear; clc;
output_precision(7);  #implicitly is set to 5 digits


# Sorry, but for now, other comments are still in Czech due to time constraints.
# Only program inputs and outputs are translated.


global Cestafile = ''; # určení typu jde snad jen přiřazením hodnoty, cocoti
                       # a viz poznámka tady u globál UzJePsFile = ...



global Iniplk = struct(); #vytvoření prázdné (staré) struktúry jako zobální
#a obsazení této staré struktúúry
Iniplk.zpracdat = 'Method of data processing = ';
Iniplk.cestafile = 'Last processed path to data file = ';
Iniplk.amplharmveV = 'Amplitude of drawn harmonics in V (1 is V, 0 is dB) = ';
Iniplk.pouzBT = 'Use Butterworth low pass filter (yes, other is no) = ';
Iniplk.fsmikBT = 'Butterworth low-pass filter cutoff frequency [Hz] = ';
Iniplk.radBT = 'Butterworth low-pass filter order (range 1 to 8, otherwise 2nd order will be used) = ';
Iniplk.PocKrHarm = 'Number of drawn harmonics = ';
Iniplk.PocPocHarm = 'Number of calculated harmonics = ';
Iniplk.PoziceFig = 'Position of figure (window) when program ends = ';




global Jminifile AmplHarmV Velpistisk;




# variable ZpracDat can only have following values:
#
#   1 = "Process data as whole cycles from first zero crossing"
#   2 = "Process data as whole cycles from first maximum"
#   3 = "Process data as whole cycles from beginning of file"
#   4 = "Process data from entire file"
#
# predefined value (even when reading config file) is 1
global ZpracDat = 1;
global VsechnyVybery = false;




global Fsmik RadBTfiltru JeBTfiltr;     #více proměnnných v řádku MUSÍ být BEZ
                                        #oddělovačů (oddělených jen mizerami)


global Monitory Hlmonitor;


global Cestafile Jmfile hgrf1 hgrf2 men Velpis;


global rel_pos_leg rel_pos_leg_BT;


global Osciloskop = "";
global OscHAN = "HANTEK DSO4102C";
global OscOWO = "OWON ADS800/900";


# následuje vytvoření řetězcového vektoru - musí být ve složených zátvorkách
global plknastpod;
plknastpod = {"Process data as whole cycles from first zero crossing" , ...
              "Process data as whole cycles from first maximum" , ...
              "Process data as whole cycles from beginning of file" , ...
              "Process data from entire file"};

global PocKresHarm PocPocHarm PocHarm FposlHarm Fvypis FpocTHD;
PocKresHarm = 200;  # preparát, dyby v ini filé nebylo
PocPocHarm = 2;

global JednHlWosyX JednHlWosyY JednWY;


global HlavPlk = 'Calculation of harmonic distortion (THD) using discrete Fourier transform';
global hfig1;


global TlacimFiguru;
TlacimFiguru = false;


global ps_file;

# Gdyš je takto deklarováno a hned v deklaraci je přiřazena hodnota,
# tak se hodnota přiřadí JEN při spuštění oktávového prostředí a při
# dalším spouštění přes F5 se už tady nepřiřazuje, ale kdyby byla hodnota
# tady přiřazována až v dalším řádku tak se hodnota přiřadí při každém
# spuštení (třeba přes F5) - tak jako jinde v programu při jeho běhu:
global UzJePsFile = false; # takto schválně, páč PS filé se maže při ukončování
                           # celé oktáávy, aby zbytečně nepsalo na HD



global PocVolTam PocVolVen;
PocVolTam = 0;
PocVolVen = 0;


global ZaklVelFig = struct(); #vytvoření prázdné (staré) struktúry jako zobální
#a obsazení staré struktúúry - násobky pro výpočet zákl. velikosti figúry
ZaklVelFig.X = 0.01;
ZaklVelFig.Y = 0.06;
ZaklVelFig.Sir = 0.97;
ZaklVelFig.Vys = 0.87;













#++++++ funkce volané z událostí +++++++++++++++++++++++++++++++++++++++++++++++



#...............................................................................
function Oktavasezavira;
   # Funkce, se volá při zavírání celé oktáávy.
   # Je tu qůli výmazu filé Póówlšelllu, které se používá k indikaci, jeli
   # aktiwní vokno maxima lízováno. Filé mazat AŽ PŘI UKONČOVÁNÍ OKTÁÁVY,
   # protože kdyby se mazalo při ukončování figúúry, bylo by to jednak
   # zbytečně často, a druhak a HLAVNĚ by se taky musela nějak vypucovat
   # inicialízační proměnná v podprogramu je_maximalizov_okno_s_focusem(),
   # páč bez výpucu zústane true a při dalším otevření figůry se filé nevytvoří
   # a podprogram ho taky nenajde, takže podprogram projde, bude hlásit
   # chybu a tím pádem se maximalízace okna bude určovat JEN z vodorovného
   # rozměru, což nemusí vždy odpovídat...


   global ps_file;


   try
     delete(ps_file);
   end_try_catch

endfunction#....................................................................






#...............................................................................
function Figurasezavira(src);
   # Funkce, se zavolá při zavírání objektu s handlem src


   #POZOR:
   # gdyš se tato fuňkce volala z definice příkazem set(... a měla jako
   # předávané párametry ještě nějaké jiné než src (byly to Jminifile, velobr, xrozl
   # tak se sem předávaly jejich hodnoty které byly v okamžiku volání
   # přikazu set(... a nebralo to ohled na jejich pozdější změny!!!!!
   # Tady to vadilo u xrozl, páč ta se může měniti, ostatní dvě asi néé.
   # Takže jsem je udělal všechny preparát zobální a funguje to.
   #pohof.


   global Jminifile;



   UlozInifile (Jminifile);



   #POZOR:
   #  jeli volání této udalosti aktívováno, MUSÍ se tady objekt s handle src
   #  taky zavříti, když tu zavření nebude tak zůstane otevřený a v Oktávě
   #  potom nejde jinak zavřít než s celou Oktávou !!!!!
   #pohof.

   try
     delete(src); # Zavření oného, musí být delete, close zde jaksi nefunguje
   catch
     # praparát, ale dyš to zblbne tak zmenšenou figůru stejně nesmaže...
     close all;            #smaže fšecky figůůry
   end


endfunction#....................................................................




#...............................................................................
function volani_tlac_plkboxu(~, ~)  #prázdný vstupy tam musí být, jinak řve botu

    #Zabudovaná fuňkce gcbf ():
    #Vrátí handle k figure obsahují objekt, jehož zpětné volání se právě provádí.


    # Zavření figuury při stisknutí tlačítka
    uiresume(gcbf); # Pokračuje v provádění po stisknutí tlačítka

endfunction#....................................................................





#...............................................................................
function omezeni_rozmeru(hzdroj,~)

  # Omezení rozměrú figúry s handle hzdroj tak aby byly v nějakých mezích
  # kdy ještě nejsou plky přes sebe (miminum) anebo aby nebylo přes dva
  # monitory, dyš sou (maximumo). Funkce se volá následovně:
  #     set(hFig, 'sizechangedfcn', @(h,ev) omezeni_rozmeru(h));
  # kde hFig je handle dotyčné figúry (tady je to hzdroj) a to zpúsobí,
  # že je volána (většinou vícekrát) když probíhá změna velikosti oné figúry.
  # L. Ruffer



  global TlacimFiguru Hlmonitor;
  global PocVolTam PocVolVen;


  PocVolTam++;

  # Funkce volá sama sebe (rekurze) třeba při provedení příkazu k nastavení
  # velikosti figúry set(hzdroj,'position',pos) a možná i při změně jednotek
  # a při takové rekurzi hrozí zacyklování, takže aby se funkce nezacyklovala
  # používám tady (po pokusech s více všelijakými možnostmi) počítání
  # vstupů do funkce a výstupú z funkce do dvou proměnných PocVolTam
  # a PocVolVen deklarovaných jako global v hlavním programu (aby byly jen
  # jednou v paměti a viděly na ně všechny instance volané funkce)
  # a vyskakuje se až při rovnosti vstupů a výstupú (u výstupu se proměnná
  # samozřejmě zvýší když už je jasné, že bude následovat výskok a poté se
  # rovnost vyhodnocuje). K provedení více čekajících instancí podprogramu
  # používám příkaz pause(jeho popis je kousek dáál), ten způsobí mj. provedení
  # nějakých čekajících volání tohoto podprogramu, ale nevím jak zjistit
  # příkazem oktávy kolik volání čeká, a kolík už vyskočilo na pause a pod.
  # a když jsem tady začal vyskakovat pro zbytečná volání dříf, nedařilo se
  # mě dopočítat stejného počtu výskoků protože jsem měl příkaz pause ještě
  # před přidáním do proměnné počítající vstupy. Takže přidávání počtu vstupů
  # (proměnná PocVolTam) MUSÍ být před voláním příkazu pause() a jiných na
  # které to vyskakuje (mj. taky drawnow), páč na ně to vyskakuje což
  # samozřejmě způsobí další zavolání tohoto podprogramu, ve kterém by se
  # počet vstupů už nepřičetl a byl by v tom boordéél...
  if (PocVolTam - PocVolVen) > 1
    PocVolVen++;
    return;
  endif


  # Protože výstup (tisknutí) figúúry do .jpg volá taky změnu rozměrů
  # a provedení oného dál dělalo boordéél (nevytiskla se figura do obrazového
  # filé ve fuňkci Ulozdofile - tamější příkaz print), tak je tu následující
  # výskok přes TlacimFiguru když je tisk do .jpg
  if TlacimFiguru
    PocVolVen++;
    return;
  endif





  # Dyš je maxima líízace tak véén bez ničeho a hned, aby maxima blízace
  # zústala a funkce nechala figúúru maximalízovanou.
  [Bota, JeMaximaBliizace] = je_maximalizov_okno_s_focusem();
  if length(Bota)>0
    # Ošetření případné obuvi při zjišťování maxima blízace PowerodeŠelem.
    #
    # Tady aspoň zjištěním jeli šířka wokna zhruba stejná jako šířka monitoru,
    # oboje v logických pixelech a jen šířka je tu proto, že aspoň u W11
    # jakštakš sedí (W11 by už neměly mít možnost přemísťovat hlavní
    # panel), ale u W10 to bude fungovat jen když bude hl. panel doole,
    # no aspoň ňěco...
    posmaxim = round(get(hzdroj,'position'));

    # Zdá se, že stačí tole rance 7 pikslí:
    JeMaxSir = abs(posmaxim(3) - Hlmonitor.sirkaLogic) <= 7;
    JeMaximaBliizace = JeMaxSir;


    # a výstup chybových plků aspoň do Commmand okna
    printf('\n\nAn error occurred while determining whether figure was maximized:');
    printf('\n\n%s', Bota);
    printf('\n\nEnd of error text ----------------------------%s', newline);
  endif
  if JeMaximaBliizace
    PocVolTam = 0;
    PocVolVen = 0;
    return;
  endif







  # Protože jsem nikde nenašel možnost (ani přes IÁÁ) říct oktávě, že má fčííl
  # udělat všechny příkazy ve frontě (stack?) je to tu uděláno přes fuňkci
  # pause(sevteřiny), protože v dokumentaci oktávy se k pause praví: "I když
  # je program pozastaven, Octave stále zpracovává vykreslování obrázků
  # a provádění grafických zpětných volání". Ovšem podle mých pokusů musí mít
  # pauza zadaný nějaký čas aby se to provedlo, při kratším neudělá nic.
  # A otázka je, jestli ten čas není závislý taky na rychlosti daného
  # počítače, to by pak někde můj čas tady použitý nemusel stačit, ale zase
  # to nechci mít zapauzované dlouho, aby to zbytečně neotravovalo...
  pause(0.2);







  # Načtení limitů uložených v figúre v ÚserData.
  # Je to v PIKSLÍCH , protože v programu jsou jednotky figúry
  # nastaveny na PIKSLE.
  # Tedy kromě přepnutí normalized - piksle při posledním volání, jehož
  # důvod je popsán u něj.
  s = get (hzdroj, 'UserData');


  # Pozici pro nastavení zjistiti až tady (a znovu), aby zjištění bylo
  # až po výskocích - může se lišit od zjištění na začátku podprogramu...
  pos = round(get(hzdroj,'position'));
  sir = pos(3); vys = pos(4);


  # Omezení hodnot na povolený rozsah (round proto, že piksely jsou celá čísla
  # a nejsou možné desetiny, pak by se s celým číslem v pos() dále nerovnalo)
  Omez_sir = round(min(max(sir, s.minSir), s.maxSir));
  Omez_vys = round(min(max(vys, s.minVys), s.maxVys));


  # qůli níže popisovanému blbnutí oktáávy (nevím proč, možná blbnu já)
  # je přidání a vynulování následujících oných tady, ocaď to už stejně
  # vyskočí
  PocVolVen++;
  if PocVolTam == PocVolVen
    PocVolTam = 0;
    PocVolVen = 0;

    # Někdy se stane (asi gdyš je myš při tažení pro změnu rozměrů mimo
    # miminální rozměry figůůry - nahoře a v levo) že se figůůra
    # nenastaví i když příkaz set má pole rozměrů pos() jedlé a zůstane
    # malá (někdy v obou rozměrech a někdy jen v jednom podle pozice myši)
    # no a zdálo se mě (i kdyš jsem nespal) že by mohla pomoct následující
    # změna jednotek (asi musí být obě změny), ale nepomúže vždy...
    set (hzdroj, 'units','normalized');   # normalízace
    set (hzdroj, 'units','pixels');
  endif



  MimoVobrazofku = false;
  # korekce začátku na výšku dyš by wrch byl někde mimo vobražofku nebo dyby
  # bylo víc jak 3/4 wokna pod wobra žofkou
  if (pos(2) + pos(4) > s.maxVys) || (pos(2) + pos(4)*0.75 < s.zacY)
    MimoVobrazofku = true;
  endif

  #korekce začátku na šířku dyš by bylo víc jak 3/4 okna mimo vobražofku
  if (pos(1) + pos(3)*0.25 > s.maxSir) || (pos(1) + pos(3)*0.75 < s.zacX)
    MimoVobrazofku = true;
  endif



  if Omez_sir ~= sir || Omez_vys ~= vys || MimoVobrazofku

    if Omez_sir ~= sir || Omez_vys ~= vys
      pos(3) = Omez_sir;
      pos(4) = Omez_vys;
    endif



    if pos(2) + pos(4)*0.75 < s.zacY
      pos(2) = s.zacY;
    elseif (pos(2) + pos(4) > s.maxVys)
      pos(2) = s.maxVys - pos(4);
    endif

    if pos(1) + pos(3) * 0.75 < s.zacX
      pos(1) = s.zacX;
    elseif (pos(1) + pos(3) * 0.25 > s.maxSir)
      pos(1) = s.maxSir - pos(3);
    endif


    set(hzdroj,'position',pos);
    drawnow ("expose");


    # protože změna rozměrů figuury někdy umístí legendy gřafu doprčic (někam
    # mimo původní umístění nebo i mimo gřaf a pak nejsou viděti) je tu
    # volání následující fuňkce aby se umístění legend předělalo
    try
      umisti_legendy(hzdroj)
    end

  endif


endfunction#....................................................................





























#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#++++++ funkce volané ocaď ++++++++++++++++++++++++++++++++++++++++++++++++++++






#...............................................................................
function [Bota, vystup] = je_maximalizov_okno_s_focusem();
    # od IÁÁ Claude Haiku 4.5 ze dne 29.1.2026 - upr. ŇUF


    % Funkce zjišťuje, zda je AKTIVNÍ okno (s fokusem) maximalizováno
    % (optimalizovaná verze - soubor se vytvoří jen jednou)
    %
    % Syntaxe:
    %  [Bota, vystup] = je_maximalizov_okno_s_focusem()
    %
    % Výstup:
    %   vystup - logická hodnota (true/false)
    %           true = okno je maximalizováno
    %           false = okno není maximalizováno
    #   Bota -  v případě průběhu bez chyby je prázdné (length(Bota) = 0)
    #           v případě chyby je tam chybové hlášení (text)
    %
    % Poznámka:
    %   Soubor se vytvoří jen při prvním volání a zůstane v tempdir
    %   Vhodné pro časté volání (např. z resize eventů)
    #
    # Aby v temp adresáři soubor nesmrďéél tak na konci hl. programu se má
    # smazat, tady je to uděláno na začátku hl. programu definicí funkce,
    # která se spustí při ukončování celé oktáávy, a to příkazem:
    #   atexit('jméno oné funkce')

    global ps_file UzJePsFile;



    Bota = '';

    # Inicializace jen při prvním volání po spuštění Oktááve
    # (je zajištěno globáál deklarací na začátku v hl. programu)
    if UzJePsFile == false
        % Vytvoření dočasného souboru (jen jednou)
        temp_dir = tempdir();
        ps_file = fullfile(temp_dir, 'Octave-je_maximalizov_okno_s_focusem.ps1');

        % PowerShell skript
        ps_code = sprintf([...
            'Add-Type @"\n' ...
            'using System;\n' ...
            'using System.Runtime.InteropServices;\n' ...
            'public class WindowState {\n' ...
            '    [DllImport("user32.dll", SetLastError = true)]\n' ...
            '    public static extern IntPtr GetForegroundWindow();\n' ...
            '    [DllImport("user32.dll", SetLastError = true)]\n' ...
            '    public static extern bool IsZoomed(IntPtr hWnd);\n' ...
            '}\n' ...
            '"@\n' ...
            '$hWnd = [WindowState]::GetForegroundWindow()\n' ...
            'if ($hWnd -ne 0) {\n' ...
            '    if ([WindowState]::IsZoomed($hWnd)) {\n' ...
            '        Write-Host "1"\n' ...
            '    } else {\n' ...
            '        Write-Host "0"\n' ...
            '    }\n' ...
            '} else {\n' ...
            '    Write-Host "0"\n' ...
            '}\n']);

        % Zápis skriptu do souboru (jen jednou)
        try
            fid = fopen(ps_file, 'w');
            fprintf(fid, '%s', ps_code);
            fclose(fid);
            UzJePsFile = true;
        catch exception
            Bota = cstrcat('When creating file, there is a function error: je_maximalizov_okno_s_focusem %s', exception.message);
            UzJePsFile = false;
            vystup = false;
            return;
        end
    end

    try
        % Spuštění PowerShell skriptu (bez zápisu - jen čtení a spuštění)
        cmd = sprintf('powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%s"', ps_file);
        [status, output] = system(cmd);

        % Zpracování výstupu
        if length(strtrim(output)) > 1
          # je obuf, jedlá odpověď je 0 nebo 1, při chybě je tam chybový plk
          Bota = strtrim(output);
          vystup = false;
        else
          output = strtrim(output);
          vystup = strcmp(output, '1');
        endif

    catch exception
        % V případě chyby vrátit false
        Bota = cstrcat('Function error: je_maximalizov_okno_s_focusem %s', exception.message);
        vystup = false;
    end

endfunction#....................................................................











#...............................................................................
function [Bota, Monitory] = Zjisti_monitory()

  # načtení hodnot o monitourech jinak, dyš to oktááva neumí, ale jen we Voknech

  # deklarace prázdného oného
  Monitory = struct('primarni', {}, 'sirkaSkut', {}, 'vyskaSkut', {}, ...
                    'zvetseni_proc', {}, 'sirkaLogic', {}, 'vyskaLogic', {},...
                    'rucni_vstup', {});


  Bota='';
  [Bota, monLogicke] = Zjisti_monitory_PS();
  if length(Bota)>0, return; end     #je obuf

  [Bota, DPI_ef] = Zjisti_DPI_ef();
  if length(Bota)>0, return; end     #je obuf


  for i=1 : numel(monLogicke)
    Monitory(i).sirkaLogic = monLogicke(i).widthLogic;
    Monitory(i).vyskaLogic = monLogicke(i).heightLogic;
    Monitory(i).zvetseni_proc = (DPI_ef(i,1)/96)*100;
    Monitory(i).primarni = monLogicke(i).primary;

    # oboje zaokrouhlit podle pravidel zaokrouhlování, round kladné hodnoty
    # okrrouhlí takto: 2.4 = 2; 2.6 = 3, záporné tu snad nebudou
    Monitory(i).sirkaSkut = round(Monitory(i).sirkaLogic * ...
                            Monitory(i).zvetseni_proc/100);
    #výšku preparát brát z Y
    Monitory(i).vyskaSkut = round(Monitory(i).vyskaLogic * (DPI_ef(i,2)/96));

    Monitory(i).rucni_vstup = 0;
  endfor

endfunction#....................................................................





#...............................................................................
function [Bota, monitors] = Zjisti_monitory_PS()

  # Funkce pro přečtení rozlišení displejů počítače vytvořená IÁÁ, éé pardon AI
  # GPT-5 mimi a voláním příkazu Poweršellu 11.1.2026.

  # Vrátí pole struktur s poli: deviceName, widthLogic, heightLogic, x, y, primary

  # Vrací rozlišení v tzv. "logických" pikslech, a pokud je we voknech
  # na oném (nebo oných) displjejích nastaveno nějaké zvětšení, tedy
  # měřítko větší jak 100% bude rozlišení v logických pikslech přiměřeně menší.
  # Wokenice používají jako 100% rozlišení 96 DPI, tedy mělo by být:
  #   96 DPI = 100%, 120 DPI = 125%, 144 DPI = 150% a to tady čte fuňkce
  # Zjisti_DPI_ef().
  # Já mám na hl. monitoru we woknech nastaveno zvětšení 150%, takže pro tento
  # monitor tato funkce vrátí X rozlišení 3840/1,5 = 2560 logických pikslí
  # (což vrací) a pro druhý monitor mám zvětšení 125%, takže 2560/1,25 = 2048
  # log. pikslí atd.


  # Výpis z podprogramu do Command wokna woktáwy se tam, odkud se volá
  # (NEE TADY) dá udělat třeba takto (tady MUSÍ být zapoznámkováno):
  #    [Bota, mon] = Zjisti_monitory_PS();
  #      for i = 1:length(mon)
  #        fprintf('Monitor %d (%s): %dx%d at (%d,%d) primary=%d\n', i, ...
  #                mon(i).deviceName, mon(i).widthLogic, mon(i).heightLogic, ...
  #                mon(i).x, mon(i).y, mon(i).primary);
  #      end


  Bota = '';

  monitors = struct('deviceName', {}, 'widthLogic', {}, 'heightLogic', {}, ...
                    'x', {}, 'y', {}, 'primary', {});

  % PowerShell příkaz: použije System.Windows.Forms.Screen
  ps_cmd = [
    'powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; ', ...
    '$s = [System.Windows.Forms.Screen]::AllScreens | ForEach-Object { ', ...
    '  [PSCustomObject]@{ deviceName=$_.DeviceName; widthLogic=$_.Bounds.Width; heightLogic=$_.Bounds.Height; x=$_.Bounds.X; y=$_.Bounds.Y; primary=$_.Primary } ', ...
    '}; $s | ConvertTo-Json -Compress"'
  ];
  [st, out] = system(ps_cmd);
  if st ~= 0
    Bota = sprintf('Subprogram Zjisti_monitory_PS returns:\n PowerShell error: %s', out);
  end
  if length(Bota)>0, return; end     #je obuf



  % Parse JSON (handle single object vs array)
  try
    j = jsondecode(out);
  catch
    % Pokud jsondecode selže, vypiš surový výstup pro diagnostiku
    Bota = sprintf('Subprogram Zjisti_monitory_PS returns:\n Unable to decode JSON from PowerShell: %s', out);
  end
  if length(Bota)>0, return; end     #je obuf




  % Normalize to array
  if isstruct(j) && ~isscalar(j)
    arr = j;
  elseif isstruct(j) && isscalar(j)
    arr = j; % ConvertTo-Json returns single object for 1 screen; keep as scalar
  else
    Bota = sprintf('Subprogram Zjisti_monitory_PS returns:\n Unexpected JSON format: %s', out);
  end
  if length(Bota)>0, return; end     #je obuf


  % Build monitors structure array
  if isscalar(arr)
    n = 1;
  else
    n = numel(arr);
  end
  monitors(1:n) = struct('deviceName', '', 'widthLogic', 0, 'heightLogic', ...
                          0, 'x', 0, 'y', 0, 'primary', false);
  for k = 1:n
    if isscalar(arr)
      item = arr;
    else
      item = arr(k);
    end
    monitors(k).deviceName = item.deviceName;
    monitors(k).widthLogic = double(item.widthLogic);
    monitors(k).heightLogic = double(item.heightLogic);
    monitors(k).x = double(item.x);
    monitors(k).y = double(item.y);
    monitors(k).primary = logical(item.primary);
  end

endfunction#....................................................................






#...............................................................................
function [Bota, dpi] = Zjisti_DPI_ef()

  # Funkce pro přečtení efektivního DPI odpovídajícího Windows škálování
  # pro všechny displeje (monitory) počítače vytvořená IÁÁ, éé pardon AI
  # GPT-5 mimi a voláním příkazů Poweršellu 11.1.2026.

  # Stručný popis podprogramu od IAA:
  #   Podprogram před čtením DPI nastaví proces na per-monitor DPI aware
  #   (pokud API dostupné) a pak volá GetDpiForMonitor pro každý monitor
  #    — vrací efektivní DPI odpovídající Windows škálování,
  #   např. 144 pro 150%, 120 pro 125%.
  # Podprogram volá SetProcessDpiAwareness(2) (per-monitor) pokud je funkce
  # dostupná. Pokud není (velmi staré Windows), volání je ignorováno.

  # Pro každý monitor vystoupí dvě hodnoty:
  #     dpi(i,1)   je DPI ve směru X (horizontální)
  #     dpi(i,2)   je DPI ve směru Y (vertikální)
  # Hodnoty budou většinou stejné, rozdíl může být např. když by monitor měl
  # různý počet bodů na palec horizontálně a vertikálně.

  # Podprogram tedy např. pro nastavené wokenní zvětšení (škálování) 150%
  # vrátí hodnotu 144. To vychází z toho, že we vokenicích se jako výchozí
  # DPI používá hodnota 96 DPI, tedy 96 DPI = 100%. Vrácené hodnoty se tedy
  # na jedlá procenta musí přepočítat, např. pro vrácených 144 v případě 150%:
  # (144 / 96) * 100 = 150, pro vrácených 120: (120 / 96) * 100 = 125 atp.


  Bota = '';

  if ispc == 0
    Bota = sprintf('Subprogram Zjisti_DPI_ef returns:\n This subprogram only works on Windows.');
  end
  if length(Bota)>0, return; end     #je obuf



  ps_script = [
    'Add-Type -TypeDefinition @"' char(10) ...
    'using System; using System.Runtime.InteropServices; using System.Collections.Generic;' char(10) ...
    'public static class DPIHelper {' char(10) ...
    '  private const int MDT_EFFECTIVE_DPI = 0;' char(10) ...
    '  [DllImport("shcore.dll")] public static extern int GetDpiForMonitor(IntPtr hmonitor, int dpiType, out uint dpiX, out uint dpiY);' char(10) ...
    '  [DllImport("shcore.dll")] public static extern int SetProcessDpiAwareness(int value);' char(10) ...  % 0=Unaware,1=System,2=PerMonitor
    '  [DllImport("user32.dll")] public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);' char(10) ...
    '  public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);' char(10) ...
    '  [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left, top, right, bottom; }' char(10) ...
    '  public static List<string> GetAllDpi() {' char(10) ...
    '    try { SetProcessDpiAwareness(2); } catch { /* ignore if not available */ }' char(10) ...
    '    var list = new List<string>();' char(10) ...
    '    MonitorEnumDelegate d = (IntPtr hMon, IntPtr hdc, ref RECT r, IntPtr dd) => {' char(10) ...
    '      uint x=0,y=0; int res = GetDpiForMonitor(hMon, MDT_EFFECTIVE_DPI, out x, out y);' char(10) ...
    '      if (res == 0) list.Add(string.Format("({0},{1})", x, y));' char(10) ...
    '      return true; };' char(10) ...
    '    EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, d, IntPtr.Zero);' char(10) ...
    '    return list; }' char(10) ...
    '}' char(10) ...
    '"@' char(10) ...
    '$list = [DPIHelper]::GetAllDpi();' char(10) ...
    'if ($list -eq $null -or $list.Count -eq 0) { Write-Output "" ; exit }' char(10) ...
    'Write-Output ($list -join ";" )' ];

  tf = [tempname '.ps1'];
  fid = fopen(tf,'w');
  if fid == -1
    Bota = sprintf('Subprogram Zjisti_DPI_ef returns:\n Unable to create temporary PS program.');
  endif
  if length(Bota)>0, return; end     #je obuf

  fwrite(fid, ps_script);
  fclose(fid);

  cmd = ['powershell -NoProfile -ExecutionPolicy Bypass -File "' tf '"'];
  [status, out] = system(cmd);

  delete(tf);

  if status ~= 0
    Bota = sprintf('Subprogram Zjisti_DPI_ef returns:\n PowerShell call failed: %s', out);
  end
  if length(Bota)>0, return; end     #je obuf


  out = strtrim(out);
  if isempty(out)
    dpi = zeros(0,2);
    return;
  end

  parts = strsplit(out, ';');
  n = numel(parts);
  dpi = zeros(n,2);
  for i = 1:n
    s = regexprep(parts{i}, '[\(\)\s]', ''); % odstranit závorky/mezery
    v = strsplit(s, ',');
    dpi(i,1) = str2double(v{1});
    dpi(i,2) = str2double(v{2});
  end

endfunction#....................................................................









#...............................................................................
function VobsadDilkyWos (handl, Miminum, Maximum, Wosa)

  # obsluha kreslení wos
  # ve Wosa je, pro kterou wosu se budou dílky a rozsah předělávat:
  #     když první znak bude "x" nebo "X" (s vyjímkou předchozích mizer, ty se
  #        ignorují) bude to wosa X (vodorovná),
  #        musí tedy Miminum, Maximum být hodnoty vykreslované na wosu X
  #     když první znak bude jiný bude to wosa Y (svislá)
  #        musí tedy Miminum, Maximum být hodnoty vykreslované na wosu Y
  #     (třetí wosu Z to zatím neobhospodařuje)
  #
  # handl je handle na objekt wos (gca) pro který se to dělá




  Wosa = upper(strtrim(Wosa));  # může se upravovat vstupní prom. Wosa, protože
                                # tady neleze veeen

  KratkaWosa = false;
  if Cmuchret(Wosa(1:1),"Y")==1
    KratkaWosa = true;
  endif

  [Hod] = IntervOs (Miminum , Maximum, KratkaWosa);


  # Pořadi následujících příkazů MUSÍ být takovéto:
  #      1. nastavení rozsahu,
  #      2. mood maňuál
  #      3. nastavení velkých dílků
  #      4. nastavení malých dílků
  # jinak si může některé hodnoty přeonačit (třeba dyš se nastaví malé dílky
  # dříf jak velké...


  if Cmuchret(Wosa,"X")==1;         #takto nemusí být ve Wosa jen jeden znak

    # wosa X (vodorovná)
    xlim(handl, [Hod(6), Hod(7)]);  #nastavení vypočteného rozsahu wosy handl
    set(handl,'xtickmode','manual');
    set(handl,"xtick",(Hod(1):Hod(4):Hod(2)));
    set(handl,"xminortickvalues",(Hod(6):Hod(5):Hod(7)));

  else
    # wosa Y (svislá)

    # Případné trochu zvětšení rozsahu wosy dyš se kryje s max nebo min dat
    # zatím jen u Y wosy, aby byl lííp vyděti nasnímaný průběch.
    # A u takto nastavovaných wos MUSÍ být tady a takto, aby se použilo
    # a už nezměnilo, poáč dyš jsem je měl za čtveřicí příkazů pro nastavení
    # tak tam provedený ylim() způsobuje nové přepočítání dílků podle Octave
    # a to tady nechcu...
    MaxGr = Hod(7);
    MinGr = Hod(6);
    if MaxGr <= Maximum*1.025
      MaxGr = MaxGr*1.025;
      if MaxGr > Hod(2) + Hod(4)
        #ještě enev. úprava maxima podle vel. dílků wos
        Hod(2) = Hod(2) + Hod(4);
      endif
    endif
    if MinGr >= Miminum*1.025
      MinGr = MinGr*1.025;
      if MinGr < Hod(1) - Hod(4)
        #ještě enev. úprava mimina podle vel. dílků wos
        Hod(1) = Hod(1) - Hod(4);
      endif
    endif


    ylim(handl, [MinGr, MaxGr]);  #nastavení vypočteného rozsahu wosy handl
    set(handl,'ytickmode','manual');
    set(handl,"ytick",(Hod(1):Hod(4):Hod(2)));
    set(handl,"yminortickvalues",(Hod(6):Hod(5):Hod(7)));

  endif
  drawnow;



endfunction#....................................................................









#...............................................................................
function [Hod] = IntervOs (Min, Max, KratkaWosa)
  # Převzatý a upravený podprogram z programu Zpracování měření z VB6.
  #
  # Vypočte z minima a maxima hodnoty pro vosy, Max a Min by měly být skutečné
  # maximální a miminální hodnoty z kreslených dat dotyčné wosy.
  #
  # Když bude KratkaWosa = true, tak se malé dílky udělají s větším odstupem,
  # (4 nebo 5 na velký dílek místo 10 na velký dílek) aby na kratší wose
  # nebylo dílkování moc husté...
  #
  # Ve výstupu jsou výsledky uloženy takto:
  #      Hod(1)   miminum  ("kulaté" podle velkých dílků)
  #      Hod(2)   maximum  ("kulaté" podle velkých dílků)
  #      Hod(3)   průsečík (podle velkých dílků)
  #      Hod(4)   velký dílek
  #      Hod(5)   malý dílek
  #      Hod(6)   miminum  ("kulaté" podle malých dílků)
  #      Hod(7)   maximum  ("kulaté" podle malých dílků)
  #      Hod(8)   průsečík (podle malých dílků)
  #
  #  Tady spočítá všechny možnosti najednou a vybrat z nich se musí jinde




  if Max == Min
    Max = Max + 0.9;    # aby osy byly rozdílné o 1
  endif


  P = 10 ^ (floor(log10(abs(Max - Min))));

  Hod(1) = floor(Min / P) * P;
  if Min > 0
    if Hod(1) > Min
      Hod(1) = (floor(Min / P) - 1) * P;
    endif
  endif

  Hod(2) = (floor(Max / P)) * P;
  if Max > 0
    if Hod(2) < Max
      # Toto je tady proto, že fuňkce floor() (ve VB Int()) funguje tak,
      # že např. z -2.7 udělá -3, ale z +2.7 udělá 2, takže by se to tam
      # pokud bylo Max trochu větší než Hod(2) nevlezlo, a proto tam původně
      # bylo +1 furt, ale v tom případě, pokud bylo Max = Hod(2) tak to
      # zbytečně přidávalo velký dílek (u mimina výše je to kladných hodnot
      # obdobně, jen by se mělo ubírati).
      Hod(2) = (floor(Max / P) + 1) * P;
    endif
  endif




  P = log10(abs(Hod(2) - Hod(1)));

  if (P - floor(P)) < 0.30102999567
     #10^(0.30102999567)=2.000000000027717
     Hod(4) = 0.2;
     if KratkaWosa
       Hod(5) = 0.05;
     else
       #toto tady dát jen pro delší wosu páč na krátké wose je to moc jemné...
       Hod(5) = 0.02;
     endif
   elseif (P - floor(P)) > 0.69897000434
     #10^(0.69897000434)=5.000000000045835
     Hod(4) = 1;
     if KratkaWosa
       Hod(5) = 0.2;
     else
       #toto tady dát jen pro delší wosu páč na krátké wose je to moc jemné...
       Hod(5) = 0.1;
     endif
   else
     Hod(4) = 0.5;
     Hod(5) = 0.1;
  endif

  P = floor(P);
  Hod(4) = Hod(4) * 10 ^ P;
  Hod(5) = Hod(5) * 10 ^ P;





  # & je and    | je or    ~ je not   ~= je není rovno   cocoti
  if (Min <= 0) && (Max >= 0) #chce to zkratku &&
    # úprava mimina a maxima tak, aby dyš je wosa přes nulu tam nula byla dycky,
    # v tomto případě se to musí podle malých dílků upravit
    # tam, kde se v Oktááve nastavuje ylim, páč je potřeba nastavit limity
    # gřafu, a to bez změny zde spočítaného jde jen tam a v tam uvedeném pořadí
    Hod(1) = 0;
    while Min <= Hod(1) - Hod(4)
      Hod(1) = Hod(1) - Hod(4);
    endwhile

    Hod(2) = 0;
    while Max >= Hod(2) + Hod(4)
      Hod(2) = Hod(2) + Hod(4);
    endwhile

    # miminum, maximum a prusečík pro malé dílky
    Hod(6) = Hod(1);
    while Min < Hod(6)          # uprava minima na malý dílek
      Hod(6) = Hod(6) - Hod(5);
    endwhile
    Hod(7) = Hod(2);
    while Max > Hod(7)          # uprava maxima na malý dílek
      Hod(7) = Hod(7) + Hod(5);
    endwhile

  else

    # miminum, maximum a prusečík pro velké dílky
    while Min > Hod(1) + Hod(4)  # uprava minima na interval popisu
      Hod(1) = Hod(1) + Hod(4);
    endwhile

    while Max < Hod(2) - Hod(4)  # uprava maxima na interval popisu
      Hod(2) = Hod(2) - Hod(4);
    endwhile

    # miminum, maximum a prusečík pro malé dílky
    Hod(6) = Hod(1);
    while Min > Hod(6) + Hod(5)  # uprava minima na malý dílek
      Hod(6) = Hod(6) + Hod(5);
    endwhile
    Hod(7) = Hod(2);
    while Max < Hod(7) - Hod(5)  # uprava maxima na malý dílek
      Hod(7) = Hod(7) - Hod(5);
    endwhile

  endif
  Hod(3) = Hod(1);
  Hod(8) = Hod(6);



endfunction#....................................................................






#...............................................................................
function indeks = Cmuchret(vcem, co)
  # fuňkce by měla vrátiti první výskyt retězce co v retezci vcem, nebo nulu
  # gdyš tam nejni

  indeksy = strfind(vcem, co);
  if isempty(indeksy)
    indeks = 0;
  else
    indeks = indeksy(1);
  end
endfunction;#...................................................................






#...............................................................................
function aktivuj_omez_rozm(hFig)
  # Připojí ResizeFcn k figuře, aby volala funkci omezeni_rozmeru
  # při každé změně velikosti.

  # Pokud není hFig zadána, použije se gcf.
  if nargin < 1 || isempty(hFig)
    hFig = gcf;
  end

  set(hFig, 'sizechangedfcn', @(h,ev) omezeni_rozmeru(hFig));

endfunction;#...................................................................




#...............................................................................
function nastavPozLegendyRelatkOse(hOsy, hleg, rel_pos);

  # Funkce pro nastavení pozice legendy tak, jak chci jááá, tedy aby byla
  # napravo (east) vevnitř ale pod popisem wosy. Původně to bylo podle
  # IÁ GPT-5 mimi relativně k ose, což měnilo všechny párametry pozice,
  # ovšem to blbě umísťovalo pozici vodorovně páč se mě asi nedařilo najít
  # správnou relativní pozici zde v rel_pos (obsazuje se natwrdo po spuštění
  # programu), tak jsem vodorovnou pozici legendy nechal na automatizaci
  # oktávy, ta to dělá celkem dobře. Ofšem aby fungovala, JE NUTNÉ v každém
  # průchodu před zjištěním pozice legendy znovu určit její pozici AŽ po použití
  # příkazu legend(hleg,'location','southeast') (zde používám pozici vlevo dole
  # v gřafu - podle termínologie map southeast) protože jakékoliv nastavení
  # pozice legendy přes 'position' logicky způsobí změnu 'location' na 'none'
  # a v tom případě se už pozice automaticky nepřepočítává.


  # kde je:
  # hOsy:     handle oné osy
  # hleg:     handle oné legendy
  # rel_pos:  [x y sirka výška] v normalizovaných osových jednotkách


  # Získat pozice v normalízovaných jednotkách vůči figúře pro osu a pro legendu
  puv_jedn_osy = get(hOsy, "Units");
  puv_jedn_legendy = get(hleg, "Units");
  set(hOsy, "Units", "normalized");
  set(hleg, "Units", "normalized");

  # zjištění párametrů legendy pro lokaci 'southwest' legendu NESCHOVÁVAT,
  # 'hide' páč pak blbne a neobnoví pozici jedle (asi dyš je schovaná to pozici
  # nepřepočítává čico...)
  legend(hleg,'location','southeast');

  PosOsy = get(hOsy, "Position");
  PosLeg = get(hleg, "Position");


  # Původní přepočet podle IÁÁÁ, necháno preparát na památku
  # Spočítat legend pozici v normalizovaných (vzhledem k figúře) souřadnicích
  #  pos_leg_prepoc = [ PosOsy(1) + rel_pos(1)*PosOsy(3), ...
  #                  PosOsy(2) + rel_pos(2)*PosOsy(4), ...
  #                  rel_pos(3)*PosOsy(3), ...
  #                  rel_pos(4)*PosOsy(4) ];


  # moje úprava, z přepočtu IÁÁÁ používá jen korekci svislého umístění, aby
  # legenda byla pod popisem wosy, na ostatní používá automat oktávy
  pos_leg_prepoc = [ PosLeg(1), ...
                  PosOsy(2) + rel_pos(2)*PosOsy(4), ...
                  PosLeg(3), ...
                  PosLeg(4) ];


  set(hleg, "Position", pos_leg_prepoc);


  # vrátit původní jednotky a vidi telnost
  set(hOsy, "Units", puv_jedn_osy);
  set(hleg, "Units", puv_jedn_legendy);


endfunction;#...................................................................




#...............................................................................
function umisti_legendy(fig);
  # znovu umístí obě legendy tady použité podle proměnnných uložených ve figúře s handlem fig


  # legenda hl. gřafu
  hleg = getappdata(fig, "hLegHL");
  ax = getappdata(fig, "hOsyXHL");
  rel_pos = getappdata(fig, "RelPosLegHL");
  if isempty(hleg) || ~ishandle(hleg) || isempty(ax) || ~ishandle(ax)
    return;
  end

  % a umístiti
  nastavPozLegendyRelatkOse(ax, hleg, rel_pos);



  # legenda BT gřafu
  JeKresBT = getappdata(fig, "KresSmikHarm");

  if JeKresBT
    hleg = getappdata(fig, "hLegBT");
    ax = getappdata(fig, "hOsyXBT");
    rel_pos = getappdata(fig, "RelPosLegBT");
    if isempty(hleg) || ~ishandle(hleg) || isempty(ax) || ~ishandle(ax)
      return;
    end

    % a umístiti
    nastavPozLegendyRelatkOse(ax, hleg, rel_pos);
  endif

  drawnow;

endfunction;#...................................................................










#...............................................................................
function [y] = rms(x);

  #výpočet efektivní hovnoty, RMS - root mean square

	n = length(x);
	y = sqrt(sum(x.^2)/n);

endfunction;#...................................................................





#...............................................................................
function UlozInifile (Jminifile);
  #xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  #uložení do ini filé s stejným jménem jako toto spuštěné .m filé
  #a s rozšířením .NUF (snad ještě není)


  #proměnné předávané zobálně
  global Iniplk;  #aby fuňkce znala zobální proměnnné, musí se v ní
                  #znovu takto deklarovat (samozřejmě pod stejným jménem)

  global ZpracDat;
  global Cestafile;
  global AmplHarmV;
  global Fsmik RadBTfiltru JeBTfiltr;
  global PocKresHarm PocPocHarm;
  global VerzeProg;
  global Monitory;
  global hfig1;



  # Otevření filé pro zápis
  fid = fopen(Jminifile, 'w');  # 'w' je pro zápis, minulý obsach bude přepsán

  # Kontrola, zda se filé otevřelo správně
  if fid == -1
     #  filé se neotevřelo

     plkbox(cstrcat('Cannot open settings file: ',Jminifile,newline, ...
             'settings will not be saved !!!'), 'Saving to settings file');

  else

    plk = cstrcat('File with settings for Harmonic Distortion Calculation program,');
    plk = cstrcat(plk, ' version dated ',VerzeProg, newline);
    fprintf(fid, plk);   # Zápis textového řetězce do filé
    plk = cstrcat('created in the GNU Octave environment, author Luděk Ruffer  lruffer@volny.cz' ...
                 ,newline,newline );
    fprintf(fid, plk);   # Zápis textového řetězce do filé




    plk = cstrcat(newline,'Values of data processing method denotes:',newline );
    fprintf(fid, plk);
    plk = cstrcat('1 = Process data as whole cycles from first zero crossing',newline );
    fprintf(fid, plk);
    plk = cstrcat('2 = Process data as whole cycles from first maximum',newline );
    fprintf(fid, plk);
    plk = cstrcat('3 = Process data as whole cycles from beginning of file',newline );
    fprintf(fid, plk);
    plk = cstrcat('4 = Process data from entire file',newline );
    fprintf(fid, plk);
    plk = cstrcat('When another value or no value is loaded, following is set = 1',newline,newline );
    fprintf(fid, plk);


    plk = cstrcat(Iniplk.zpracdat, num2str(ZpracDat, "%d"),newline,newline);
    fprintf(fid, plk);


    plk = cstrcat(newline, Iniplk.PocKrHarm, num2str(PocKresHarm, "%d"),newline );
    fprintf(fid, plk);

    plk = cstrcat(newline, Iniplk.PocPocHarm, num2str(PocPocHarm, "%d"),newline );
    fprintf(fid, plk);

    plk = cstrcat(newline, Iniplk.amplharmveV, num2str(AmplHarmV, "%d"),newline );
    fprintf(fid, plk);



    plk = cstrcat(newline, Iniplk.cestafile);
    fprintf(fid, plk);
    #cesta se zpět. lomítky MUSÍ být uložena jako řetěz pomocí následujícího
    #formátování, jinak z ní oktáva ty zpětná lomítka vyháže!!!!!!
    fprintf(fid, '%s\n', Cestafile);


    plk = cstrcat(newline, Iniplk.PoziceFig);
    fprintf(fid, plk);
    fprintf(fid, '%d  %d  %d  %d\n', round(get(hfig1, 'position')));


    if JeBTfiltr
      plk1 = 'yes';
    else
      plk1 = 'no';
    endif
    plk = cstrcat(newline, Iniplk.pouzBT, plk1, newline);
    fprintf(fid, plk);

    plk = cstrcat(Iniplk.fsmikBT, num2str(Fsmik, "%d"),newline );
    fprintf(fid, plk);

    plk = cstrcat(Iniplk.radBT, num2str(RadBTfiltru, "%d"),newline );
    fprintf(fid, plk);




    # následují informační hodnoty, při spuštění programu se nečtou:

    plk = cstrcat(newline,newline, 'Further values are informational only,');
    plk = cstrcat(plk, ' are not read when program is launched.',newline,newline);
    fprintf(fid, plk);

    plk = cstrcat('Computer on which program runs has these monitors:',newline );
    fprintf(fid, plk);
    for i = 1:length(Monitory)
      fprintf(fid,'  Monitor %d%s',i,':   ');
      if Monitory(i).primarni
        fprintf(fid,cstrcat('  is primary;  ',char(9)));
      else
        fprintf(fid,cstrcat('  is not primary;',char(9)));
      endif
      fprintf(fid,'  width %d %s',Monitory(i).sirkaSkut,';');
      fprintf(fid,'  height %d %s',Monitory(i).vyskaSkut,';');
      fprintf(fid,'  enlargement %d%% %s',Monitory(i).zvetseni_proc,';');
      fprintf(fid,'  logical width %d %s',Monitory(i).sirkaLogic,';');
      fprintf(fid,'  logical height %d %s',Monitory(i).vyskaLogic,';');

      if Monitory(i).rucni_vstup
      fprintf(fid,cstrcat('  values entered manually'));
      else
      fprintf(fid,cstrcat('  values read by program'));
      endif

      fprintf(fid,newline);
    endfor


    plk = cstrcat(newline, 'File has been saved ');
    fprintf(fid, plk);
    # nápo věda k formátování času je u time
    fprintf(fid, strftime ("%d.%m.%Y at time of %T.", localtime (time ())), newline);


    plk = cstrcat(newline, newline,'End of settings file.',newline );
    fprintf(fid, plk);

    # Zavření filé
    fclose(fid);

  endif
#xonec ukládání xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
endfunction#....................................................................






#...............................................................................
function Jemriz = FunNufmriz (Jemriz, hgrf1, hgrf2);
  #V Oktáávě jsou v zátvorce za jménem fuňkce JEN vstupní párametry do fuňkce,
  #výstupní musí být před rovnítkem a dyš je jich víc tak v hranatejch
  #zátvorkách odděleny čárkama.


  if (Jemriz == true);
    grid (hgrf1, 'off');
    grid (hgrf2, 'off');
    Jemriz = false;
  else
    #u obouch gřafúú je to děláno takto, tak tady to tak musí býti taky
    #aby to obnovovalo mřížky u malejch dílků
    set (hgrf1, "xgrid", "on","ygrid", "on");
    set (hgrf1, "xminorgrid", "on","yminorgrid", "on");

    set (hgrf2, "xgrid", "on","ygrid", "on");
    set (hgrf2, "xminorgrid", "on","yminorgrid", "on");

    Jemriz = true;
  endif

endfunction#....................................................................







#...............................................................................
function plkbox(message, title)
    #užívatelský msg box, ale velikost by byla potřeba upravit podle vloženého plku...


    figuury = findobj('Type', 'figure');      #získání všech otevřených figur
    pocet_figur = length(figuury);            #počet otevřených figur

    if pocet_figur > 0
       cisla_figur = get(figuury, 'Number');  #čísla otevřených figuur
       maximumo = max(cisla_figur);
    else
       maximumo = 98;    # nějaké číslo které snad hned nebude
    endif
    Cfig = maximumo + 1;

    sirplku = 600;

    h = figure (Cfig, 'Name', title, 'NumberTitle', 'off', 'MenuBar', 'none', ...
               'position', [500, 500, sirplku, 150]);


    uicontrol('parent',h , 'Style', 'text', 'String', message, 'FontSize', 12, ...
              'FontWeight', 'normal', 'position', [20, 70, sirplku - 25, 50], ...
              'HorizontalAlignment', 'center', 'backgroundcolor', [1 1 1]);

    sirtlac = 100;
    uicontrol('parent',h ,'Style', 'pushbutton', 'String', 'OK', 'position', ...
              [sirplku/2 - sirtlac/2, 20, sirtlac, 30], ...
              'Callback', @volani_tlac_plkboxu);


    #Čekání na stisk tlačítka
    uiwait(h);  # Pozastaví provádění, dokud není figure zavřena nebo tlačítko stisknuto

    try
      # dyš se figure s plkem zavře křížkem v rohu je tady už zavřená
      # a close(h) nemá co zavírat tak udělá botu
      close(h);
    end


end#............................................................................









#...............................................................................
function [hgrf1, hgrf2] = UlozdofileMensi (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis);

[hgrf1, hgrf2] = Ulozdofile (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, '-r300', ', lower resolution');

endfunction#....................................................................



#...............................................................................
function [hgrf1, hgrf2] = UlozdofileVetsi (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis);

[hgrf1, hgrf2] = Ulozdofile (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, '-r600', ', higher resolution');

endfunction#....................................................................





#...............................................................................
function [hgrf1, hgrf2] = Ulozdofile (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, Rozlis, plkroz);

  #nakreslí se znovu s písmem jedlým pro tisk, vytiskne se a překreslí se
  #s písmem pro vobra žofku


  global Velpistisk;
  global TlacimFiguru;


  plk = cstrcat("Enter name for saving to file (as image formats)", ...
                plkroz);
  [fjmeno, fcesta, fpocet] = uiputfile ({"*.jpg","Image jpg"; "*.gif", "Image gif"; ...
                         "*.tif","Image tif"; "*.png", "Image png" }, ...
                         plk, Cestafile);


  if fpocet < 1
    odp = msgbox('No file has been selected for saving, nothing will be saved.' , ...
                'Saving to file');
    return;
  endif


  mysisko = get (gcf, 'pointer');
  set (gcf, 'pointer', 'watch');  #čekatiti'''''''''''''''''''''''''''''''''''''
  set (men.zaklovl, "enable", 'off');
  set (men.zakledit, "enable", 'off');

  Tlacenice = cstrcat(fcesta , fjmeno);

  plkfig = get(gcf, 'name');
  plk = cstrcat(plkfig, ' - Wait a minute, pushing into file: ',Tlacenice);
  set (gcf, 'name', plk);




  TlacimFiguru = true;

  ZaklPosFig = getappdata(gcf,'ZaklPosFig');
  VcilJednFig = get (gcf, 'units');
  set (gcf, 'units', 'normalized');
  VcilPosFig = get (gcf, 'position');

  # úprava pozic legend pro výstup do obrazového filé
  ZaklPosLegHL = getappdata(gcf,'RelPosLegHL');
  ZaklPosLegBT = getappdata(gcf,'RelPosLegBT');
  ZaklPosLegHLup = ZaklPosLegHL;
  ZaklPosLegBTup = ZaklPosLegBT;
  ZaklPosLegHLup(1) = ZaklPosLegHL(1) - 0.008;   # úprava počátku výšky umístění
  ZaklPosLegHLup(2) = ZaklPosLegHL(2) - 0.035;   # úprava počátku výšky umístění
  ZaklPosLegBTup(1) = ZaklPosLegBT(1) - 0.045    # úprava počátku šířky umístění
  ZaklPosLegBTup(2) = ZaklPosLegBT(2) - 0.075;   # úprava počátku výšky umístění
  setappdata(gcf,'RelPosLegHL', ZaklPosLegHLup);
  setappdata(gcf,'RelPosLegBT', ZaklPosLegBTup);


  MeniloTuRozmery = false;
  if all(ZaklPosFig == VcilPosFig) == false
    # při takto udělané podmínce se sem dostane kdyš nebudou všechny prvky
    # dotyčných polí stejné (stačí jeden různý)

    MeniloTuRozmery = true;
    set (gcf, 'position', ZaklPosFig);
  endif



  #některé výstupní proměnnné tady nejsou potřeba
  [ ~, ~,  ~, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, ...
                                      Velpistisk, [], false, true, true);

  print (gcf,Tlacenice , Rozlis);

  # vrácení původních pozic tady, aby v následujícím VypDFT překreslilo
  setappdata(gcf,'RelPosLegHL', ZaklPosLegHL);
  setappdata(gcf,'RelPosLegBT', ZaklPosLegBT);

  [ ~, ~,  ~, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, ...
                                      Velpis , [], false, true, false);


  if MeniloTuRozmery
    # eště dyš jsou rozměry normálízed a je TlacimFiguru tak vrátiti rozměry
    # jaký byly při vstupu sem
    set (gcf, 'position', VcilPosFig);
  endif




  TlacimFiguru = false;



  set (gcf, 'units', VcilJednFig);
  set (gcf, 'name', plkfig);
  set (men.zaklovl, "enable", 'on');
  set (men.zakledit, "enable", 'on');
  set (gcf, 'pointer', mysisko); #nečekatiti''''''''''''''''''''''''''''''''''''


endfunction#....................................................................










#...............................................................................
function PrejezZprac (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, NoveZprac);

#přepočítá a překreslí výstup (figúúru) pro nově zadaný zpúsob zpracování
# (od průchodu nulou, od maxima, celé filé a tak)


global ZpracDat



#dyš je stejné jak minulé tak vééén
if ZpracDat == NoveZprac
  return;
end


mysisko = get (gcf, 'pointer');
set (gcf, 'pointer', 'watch');  #čekatiti'''''''''''''''''''''''''''''''''''''''
set (men.zaklovl, "enable", 'off');
set (men.zakledit, "enable", 'off');



plkfig = get(gcf, 'name');
plk = cstrcat(plkfig, ' - One moment, reprocessing data');
set (gcf, 'name', plk);


ZpracDat = NoveZprac;


# zafajfkování aktuálního menu pro zpracování dat z filé
for i = 1: length(men.nastpod)
  set(men.nastpod(i), "checked", "off")
endfor
set(men.nastpod(ZpracDat), "checked", "on")




#přeježení pro nové ZpracDat - některé výstupní proměnnné tady nejsou potřeba
[ ~, ~,  ~, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, ...
                                    Velpis , [], false, false, false);




set (gcf, 'name', plkfig);
set (men.zaklovl, "enable", 'on');
set (men.zakledit, "enable", 'on');
set (gcf, 'pointer', mysisko); #nečekatiti''''''''''''''''''''''''''''''''''''''


endfunction#....................................................................








#...............................................................................
function ZmenKreslHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis);


global AmplHarmV;


mysisko = get (gcf, 'pointer');
set (gcf, 'pointer', 'watch');  #čekatiti'''''''''''''''''''''''''''''''''''''''

plk = cstrcat("Switch [dB - V] for drawing Y-axis of graph of harmonics: now it is ");
if AmplHarmV == 0
  AmplHarmV = 1;
  plk = cstrcat(plk, 'in [V]');
else
  AmplHarmV = 0;
  plk = cstrcat(plk, 'in [dB]');
end


set (men.nastpodharm, 'text' , plk);
set (men.kontmenu.nastharm, 'text' , plk);


#přeježení pro nové kreslení harmonických - některé výst. prom. nejsou potřeba
[ ~, ~,  ~, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, ...
                                    Velpis , [], false, true, false);

set (gcf, 'pointer', mysisko);  #ne čekatiti''''''''''''''''''''''''''''''''''''


endfunction#....................................................................








#...............................................................................
function ZmenPocKreslHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis);


  global PocKresHarm PocHarm FposlHarm Fvypis;


  mysisko = get (gcf, 'pointer');
  set (gcf, 'pointer', 'watch');  #čekatiti'''''''''''''''''''''''''''''''''''''




  plk = cstrcat('Enter last harmonic, after which harmonics will be drawn in their graph,' ...
      ,newline, 'now is last plotted harmonic:'...
      ,newline, '   ', num2str(PocKresHarm + 1,'%d'), char(9), char(9)...
      ,'i.e. up to frequency ',num2str(sigfig(Fvypis/1000,4)),' kHz'...
      ,newline, 'last possible harmonic for processed file is:'...
      ,newline, '   ', num2str(PocHarm + 1,'%d'), char(9), char(9)...
      ,'i.e. up to frequency ',num2str(FposlHarm/1000, "%d"),' kHz'...
      ,newline, newline, 'If a value less than 20 is entered, input will be adjusted to 20,'...
      ,newline, 'when entering a value greater than that contained in calculation from processed'...
      ,newline, 'file, input will be adjusted to calculated number of harmonics.');


  plktit = 'Entering of last harmonic in graph.';
  defaults = {PocKresHarm + 1};
  rowscols = [1,10];
  vlozeno = inputdlg (plk ,plktit ,rowscols , defaults);

  if isempty(vlozeno)
    # vstup zrušen Cancel => véééén
    set (gcf, 'pointer', mysisko);  #ne čekatiti''''''''''''''''''''''''''''''''
    return;
  endif

  if isnan(str2double(vlozeno{1}))
    #je to NáN (Not a Number)
    vstup = PocKresHarm;
  else
    #je to muňkové pole(může obsahovat v muňkách různé
    #typy dat, tady řitěz), musí se převést na číslo...
    vstup = fix(str2double(vlozeno{1}));
  endif


  if vstup - 1 == PocKresHarm
    set (gcf, 'pointer', mysisko);  #ne čekatiti''''''''''''''''''''''''''''''''
    return;    #nic se nezměnilo => véééén
  endif


  if vstup < 20
    vstup = 20;  #miminum pro kreslení
  endif

  if vstup - 1 > PocHarm
    vstup = PocHarm + 1;
  endif

  PocKresHarm = vstup - 1;

  plk = cstrcat("Change in number of plotted harmonics ");
  plk = cstrcat(plk, '(now it is ',num2str(PocKresHarm + 1, "%d"), ' i.e. up to ');
  plk = cstrcat(plk, num2str(sigfig(Fvypis/1000,4)),' kHz)');
  set (men.nastPocHarm, 'text' , plk);
  set (men.kontmenu.nastPocHarm, 'text' , plk);


  #přeježení jen nové kreslení harmonických - některé výst. prom. nejsou potřeba
  [ ~, ~,  ~, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, ...
                                      Velpis , [], false, false, false);

  set (gcf, 'pointer', mysisko);  #ne čekatiti''''''''''''''''''''''''''''''''''


endfunction#....................................................................




#...............................................................................
function ZmenPocPocitHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis);


  global PocPocHarm PocHarm FposlHarm FpocTHD;


  mysisko = get (gcf, 'pointer');
  set (gcf, 'pointer', 'watch');  #čekatiti'''''''''''''''''''''''''''''''''''''




  plk = cstrcat('Enter last harmonic for which THD will be calculated in separate line of calculation' ...
  ,newline, 'now the last calculated harmonic is:'...
      ,newline, '   ', num2str(PocPocHarm + 1,'%d'), '.', char(9), char(9)...
      ,'i.e. up to frequency ',num2str(sigfig(FpocTHD/1000,4)),' kHz'...
      ,newline, 'last possible harmonic for processed file is:'...
      ,newline, '   ', num2str(PocHarm + 1,'%d'), char(9), char(9)...
      ,'i.e. up to frequency ',num2str(FposlHarm/1000, "%d"),' kHz'...
      ,newline, newline, 'If a value less than 3 is entered, input will be adjusted to 3,'...
      ,newline, 'when entering a value greater than that contained in calculation from processed'...
      ,newline, 'file, input will be adjusted to calculated number of harmonics.');

  plktit = 'Entering of last harmonic for THD calculation.';
  defaults = {PocPocHarm + 1};
  rowscols = [1,10];  #počet [řádků,sloupců; ...] ve vst. woknech, pro každý qokno
  vlozeno = inputdlg (plk ,plktit ,rowscols , defaults);

  if isempty(vlozeno)
    # vstup zrušen Cancel => véééén
    set (gcf, 'pointer', mysisko);  #ne čekatiti''''''''''''''''''''''''''''''''
    return;
  endif

  if isnan(str2double(vlozeno{1}))
    #je to NáN (Not a Number)
    vstup = PocPocHarm;
  else
    #je to muňkové pole(může obsahovat v muňkách různé
    #typy dat, tady řitěz), musí se převést na číslo...
    vstup = fix(str2double(vlozeno{1}));
  endif


  if vstup - 1 == PocPocHarm
    set (gcf, 'pointer', mysisko);  #ne čekatiti''''''''''''''''''''''''''''''''
    return;    #nic se nezměnilo => véééén
  endif


  if vstup < 3
    vstup = 3;  #miminum pro počítání
  endif

  if vstup - 1 > PocHarm
    vstup = PocHarm + 1;
  endif

  PocPocHarm = vstup - 1;

  plk = cstrcat("Change in last calculated harmonics ");
  plk = cstrcat(plk, '(now it is ',num2str(PocPocHarm + 1, "%d"), '. i.e. up to ');
  plk = cstrcat(plk, num2str(sigfig(FpocTHD/1000,4)),' kHz)');
  set (men.nastPocPocHarm, 'text' , plk);
  set (men.kontmenu.nastPocPocHarm, 'text' , plk);


  #přeježení jen nové kreslení harmonických - některé výstupní proměnnné tady nejsou potřeba
  [ ~, ~,  ~, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis , [], false, false, false);

  set (gcf, 'pointer', mysisko);  #ne čekatiti''''''''''''''''''''''''''''''''''


endfunction#....................................................................







#...............................................................................
function [Velpis] = NastavVelPis (monitor);


  global Velpistisk;


  Velpis = 0.00438 * monitor.sirkaLogic + 4.32;
  Velpistisk = 0.00078 * monitor.sirkaLogic + 5.98;


endfunction#....................................................................












#...............................................................................
function [signalfilt] = DPButerworth (rad_filtru, signal, Fvzorkovani, kmitocet_zlomu);

#dolní Butterworthova propust řádu rad_filtru:
# první řád je -6 dB/oktáávu
# druhý řád je -12 dB/oktáávu
# třetí řád je -18 dB/oktáávu  atd.


if kmitocet_zlomu == 0
  smikfrekv = Fvzorkovani/100;
else
  smikfrekv = kmitocet_zlomu;
end



if smikfrekv/(Fvzorkovani/2) > 1;
  signalfilt = signal; # smikfrekv je mimo povolený interval, nefiltrovat
else
  % návrh Butterworthova filtru:
  [b, a] = butter(rad_filtru, smikfrekv/(Fvzorkovani/2), 'low');

  signalfilt = filtfilt(b, a, signal); # aplikace oného filtru bez zkreslení
end



endfunction#....................................................................






#...............................................................................
function NastavButt (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis);


  global Fsmik RadBTfiltru JeBTfiltr;


  RFtu = RadBTfiltru;
  KZtu = Fsmik;
  JFtu = JeBTfiltr;



  plk1 = cstrcat('Processed signal will be modified by passing through a low-pass filter, and then THD will be calculated' ...
              ,newline, '    (displayed on a separate line). This is to suppress influence of unwanted higher harmonics' ...
              ,newline, '    on THD. THD calculated after signal passes through a suitably selected low-pass filter' ...
              ,newline, '    should be lower. Butterworth filter was chosen because of its maximally flat (within' ...
              ,newline, '    possibilities of filters) characteristic in passband.'...
              ,newline, newline, 'Use low pass filter (1 = yes, other = no):');




  plk2 = cstrcat(newline, newline, 'Filter order, here it can be in range of 1 to 8,' ...
              ,newline, '    for 1st order, low-pass filter has slope of -6 dB/octave (-20 dB/decade)'...
              ,newline, '    for 2nd order, low-pass filter has slope of -12 dB/octave (-40 dB/decade)'...
              ,newline, '    for 3rd order, low-pass filter has slope of -18 dB/octave (-60 dB/decade), etc.'...
              ,newline, 'Filter order (range 1 to 8):');



  plk3 = cstrcat(newline, newline,'Cutoff frequency (Fo) is frequency at which there is an approximate -3 dB drop. It is entered here' ...
              ,newline, '    in Hz and is not limited in any way, but in order for THD calculations via low-pass filter to be' ...
              ,newline, '    acceptable, it should be higher than or equal to at least 3rd harmonic, i.e., for example, for' ...
              ,newline, '    measured frequency of 20 kHz, it should be at least 60 kHz. For lower Fo, calculated THD will be' ...
              ,newline, '    higher, which may not meet requirement for suppression of unwanted higher harmonics. Conversely,' ...
              ,newline, '    if selected Fo is higher than highest harmonic that can be calculated from given signal, low-pass' ...
              ,newline, '    filter will not apply and THD calculated through it will be the same as THD of the signal without' ...
              ,newline, '    low-pass filter.'...
              ,newline, 'Cutoff frequency [Hz]:');




  plkcel = {plk1, plk2, plk3};
  plktit = 'Entering parameters for Butterworth low-pass filter.';

  defaults = {JeBTfiltr, RadBTfiltru, Fsmik};
  rowscols = [1,10; 1,10; 1,10];
  vlozeno = inputdlg (plkcel ,plktit ,rowscols , defaults);


  Prekreslit = false;
  Blbyvstup = false;
  if isempty(vlozeno)
    #vstup byl zrušen
    Blbyvstup = true;
  endif



  if Blbyvstup
    # když byl vstup zrušen vrátiti původní hodnoty
    RadBTfiltru = RFtu ;
    Fsmik = KZtu;
    JeBTfiltr = JFtu;
  else
    if isnan(str2double(vlozeno{1}))
      JeBTfiltr = JFtu;
    else
      vstup = fix(str2double(vlozeno{1}));

      if vstup == 1
        JeBTfiltr = true;
      else
        JeBTfiltr = false;
      endif

      if JeBTfiltr ~= JFtu  # neni ho... pardon, rovno
        Prekreslit = true;
      endif
    endif



    if isnan(str2double(vlozeno{2}))
      RadBTfiltru = RFtu;
    else
      vstup = fix(str2double(vlozeno{2}));

      if (vstup > 0) & (vstup < 9)
        RadBTfiltru = vstup;
      else
        RadBTfiltru = RFtu;
      endif

      if RadBTfiltru ~= RFtu
        Prekreslit = true;
      endif
    endif



    if isnan(str2double(vlozeno{3}))
      Fsmik = KZtu;
    else
      Fsmik = str2double(vlozeno{3});
    endif

    if Fsmik ~= KZtu
      Prekreslit = true;
    endif
  endif



  if Prekreslit
    mysisko = get (gcf, 'pointer');
    set (gcf, 'pointer', 'watch');  #čekatiti'''''''''''''''''''''''''''''''''''
    set (men.zaklovl, "enable", 'off');
    set (men.zakledit, "enable", 'off');
    set (men.hlnast, "enable", 'off');

    #některé výstupní proměnnné tady nejsou potřeba
    [ ~, ~,  ~, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, ...
                                        men, Velpis, [], false, false, false);

    set (men.zaklovl, "enable", 'on');
    set (men.zakledit, "enable", 'on');
    set (men.hlnast, "enable", 'on');
    set (gcf, 'pointer', mysisko); #nečekatiti''''''''''''''''''''''''''''''''''
  endif


endfunction#....................................................................







#...............................................................................
function [FTFazeGrf] = faze(realna, imagin)


FTFaze = atan(imagin / realna);    #fáze  v Rad
FTFazeSt = FTFaze * 180.0 / pi;    #fáze  ve °


# doježení fáze na kruh 360° podle kwadrantů, páč arctan je jen +- 90°
# (= průmět na wosy Y) a přepočet fáze ve ° jako průmět na wosu Y,
# pro gřaf - v FTFazeGrf()
if sign(realna) >= 0
  #od 0° do 180°
  FTFazeGrf = 90.0 + FTFazeSt;

else
  #od 180° do 360°
  FTFazeGrf = 270.0 + FTFazeSt;
  if sigfig(FTFazeGrf, 6) == 360.0  #zaokr. na 6 plat. číslic, esi bude stačiti
    FTFazeGrf = 0;
  endif

endif

endfunction#....................................................................





#...............................................................................
function [formplk] = Formnamista(cislo, pocmist)


#jeli pocmist <=0 tak véén
if pocmist <= 0
  formplk = '%4.2f';
  return
endif



#jeli cislo = 0 tak véén
if (sigfig(cislo, pocmist) == 0)
  formplk = cstrcat('%1.',num2str(pocmist-1,'%d'),'f');
  return
endif



mista = log10(abs(cislo));
znaminko = sign(mista);
mista = fix(mista);


if mista>=0
  #cislo je >= 0,1

  if mista>=pocmist
   pred = mista;
   za = 0;
  else
   if znaminko >=0
     za = pocmist - mista - 1;  #pred musí být +1 místo pro x,xx
   else
     za = pocmist - mista;      #ale né pro 0,xx
   endif
   pred = pocmist - za;

  endif
else
  #cislo je < 0,1

  pred = 1; #nula celá, (0,xx)
  za = abs(mista) + pocmist;

  if za > 7   #pro víc jak zde daný počet míst za des. tečkou dát ee formát
    formplk = cstrcat('%1.',num2str(pocmist-1,'%d'),'e');
    return
  endif

endif


formplk = cstrcat('%',num2str(pred,'%d'),'.',num2str(za,'%d'),'f');


endfunction#....................................................................






#...............................................................................
function y = sigfig(x,n,do_round=1)
  #NUF:
  #I took liberty of using this here (I hope I didn't I took liberty too much..)

  %----------------------------------------------------------------------------
  % Jonathan R. Senning <senning@gordon.edu>
  % Gordon College
  % October 22, 2000
  % January 2015: Revised and renamed from rnd()
  %
  % Usage: y = sigfig( x, n [, do_round] )
  %
  % Returns:
  %       y:    The value of x rounded or chopped to n significant figures
  %
  % Parameters:
  %       x:    The value to round or chop
  %       n:    The number of significant decimal places to keep.
  %  do_round:  non-zero for rounding (default), 0 for truncation
  %
  % Rounds or chops x to n significant decimal places
  %----------------------------------------------------------------------------

  % Since we can't take the log of a negative number, we need to
  % strip any negative sign from x and reapply it at the end.  In
  % the event that x is zero, we just want to return zero.

  s = 1;
  if ( x < 0 )
    x = -x;
    s = -1;
  elseif ( x == 0 )
    y = x;
    return
  end

  % Compute the proper power of 10 to multiply x by so that n decimal
  % places are left to the left of the decimal point.

  a = -( floor( log10( x ) ) - ( n - 1 ) );

  % Now multiply x by 10^a, round to the nearest integer, and then
  % multiply by 10^(-a).  Also, don't forget to reapply the sign of x.

  if ( do_round ~= 0 )
    y = s * round( x * 10^a ) * 10^(-a);
  else
    y = s * fix( x * 10^a ) * 10^(-a);
  end

endfunction#....................................................................









#...............................................................................
function [Indprvmax, Indposmax, pockmitu] = UprnaPruchNulou (signal, Fvzorkovani);

  # úprava na celé kmity od 1. průchodu nulou \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\


  # odfiltrování vyšších kmitočtů, zde dolní Butterworthova propust
  [signalfilt] = DPButerworth (4, signal, Fvzorkovani,0);




  # podle gpt-4o mimi
  # Detekce křížení nuly
  pruch_nulou = find(diff(sign(signalfilt)));



  if length(pruch_nulou) > 3
    #pokus o úpravu na průchody nulou

    Indprvmax = pruch_nulou(1);
    if mod(length(pruch_nulou), 2) == 0
      #sudy
      Indposmax =  pruch_nulou(length(pruch_nulou) - 1);
     pockmitu = length(pruch_nulou)/2 - 1;
    else
      #lichy
      Indposmax = pruch_nulou(length(pruch_nulou));
      pockmitu = (length(pruch_nulou) - 1)/2;
    end

  else
    #preparát zařadit celé filé

    [Indprvmax, Indposmax, pockmitu] = UprnaCeleFile (signal, Fvzorkovani)
  end


endfunction#....................................................................







#...............................................................................
function [Indprvmax, Indposmax, pockmitu] = UprnaCeleodZac (signal, Fvzorkovani);

#úprava na celé kmity od začátku filé \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\


#odfiltrování vyšších kmitočtů, zde dolní Butterworthova propust
[signalfilt] = DPButerworth (4, signal, Fvzorkovani,0);


poc_bodu_sign = length(signal);                   #z celého signálu
Trvani_signalu = poc_bodu_sign / Fvzorkovani;     # v sevteřinách
# Detekce kmitů, tady z filtrovaného signálu
praach=0.15*abs(max(signalfilt)); # prahová hodnota pro detekci, zde 15% maxima

# indeksy nulových průsečíkúú (takto celých cyklů)
Ind_0prus = find(signalfilt(1:end-1) < praach & signalfilt(2:end) >= praach);

Prum_vzd_ind = mean(diff(Ind_0prus));  #průměrný rozdíl indeksú průsečíkú
Cas_1kmitu = Prum_vzd_ind * (1/Fvzorkovani);  # v sevteřinách
pockmitu_skut = Trvani_signalu / Cas_1kmitu;


wocas_kmitu = pockmitu_skut - fix(pockmitu_skut);  #fix ušmikne celé číslo
if abs(1 - wocas_kmitu) < 0.0075
  wocas_kmitu = 0;
  pockmitu_skut = fix(pockmitu_skut) + 1;
end

wocas_v_indexech = fix((Cas_1kmitu * wocas_kmitu) / (1/Fvzorkovani));


Indprvmax = 1;
Indposmax = poc_bodu_sign - wocas_v_indexech ;
pockmitu = fix(pockmitu_skut);  #tady na celé kmity

endfunction#....................................................................









#...............................................................................
function [Indprvmax, Indposmax, pockmitu] = UprnaCeleodMax (signal, Fvzorkovani);

#úprava na celé kmity od 1. maximuma \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\



#odfiltrování vyšších kmitočtů, zde dolní Butterworthova propust
[signalfilt] = DPButerworth (4, signal, Fvzorkovani,0);

MinVzds_picek=fix(length(signalfilt)*0.002);

#takto najde kladné i záporné maximuma, takže do jednoho kmitu jsou DVĚ
[hodn_maxim, ind_maxim] = findpeaks(signalfilt, 'DoubleSided', ...
                                    "MinPeakDistance",MinVzds_picek);


#průměrný rozdíl indeksú, zde maximum, a ty jsou na celý kmit DVĚ
Prum_vzd_ind = mean(diff(ind_maxim)) * 2;

poc_bodu_sign = length(signal) - ind_maxim(1);    # tady od prvního maximuma
Trvani_signalu = poc_bodu_sign / Fvzorkovani;     # v sevteřinách
Cas_1kmitu = Prum_vzd_ind * (1/Fvzorkovani);      # v sevteřinách
pockmitu_skut = Trvani_signalu / Cas_1kmitu;


Ind_vsech_kmitu = fix(Prum_vzd_ind * fix(pockmitu_skut));


Indprvmax = ind_maxim(1);
Indposmax = Ind_vsech_kmitu + Indprvmax;
pockmitu = fix(pockmitu_skut);  #tady na celé kmity

endfunction#....................................................................






#...............................................................................
function [Indprvmax, Indposmax, pockmitu_skut] = UprnaCeleFile (signal, Fvzorkovani);

#úprava na celé filé - jen qůli počtu cyklúú \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

#pro výpočet počtu kmitů jsou zde pou žita maximuma


#odfiltrování vyšších kmitočtů, zde dolní Butterworthova propust
[signalfilt] = DPButerworth (4, signal, Fvzorkovani,0);


#takto najde kladné i záporné maximuma, takže do jednoho kmitu jsou DVĚ
[hodn_maxim, ind_maxim] = findpeaks(signalfilt, 'DoubleSided');


#průměrný rozdíl indeksú, zde maximum, a ty jsou na celý kmit DVĚ
Prum_vzd_ind = mean(diff(ind_maxim)) * 2;

poc_bodu_sign = length(signal);                   # tady od začátku
Trvani_signalu = poc_bodu_sign / Fvzorkovani;     # v sevteřinách
Cas_1kmitu = Prum_vzd_ind * (1/Fvzorkovani);      # v sevteřinách
pockmitu_skut = Trvani_signalu / Cas_1kmitu;


Indprvmax = 1;
Indposmax = length(signal);

endfunction#....................................................................









#...............................................................................
function [THD, ss_slozka, pockmitu, index_zakl_harm, f_vektor, jednostr_spektrum, ...
          fft_signalu_jednostr, Indexy_harmonickych] = FFTNufsTHD (signal, Fvzorkovani, kmity_z_fun);


# Výpočet Fourierovy transformace //////////////////////////////////////////////
#    částečně s pomocí gpt-4o mimi

poc_bodu_sign = length(signal);                   # ze zpracovávané části
Trvani_signalu = poc_bodu_sign / Fvzorkovani;     # v sevteřinách


fft_signalu = fft(signal);


dvoustr_spektrum = abs(fft_signalu/poc_bodu_sign);         # dvoustr. spektrum
jednostr_spektrum = dvoustr_spektrum(1:poc_bodu_sign/2+1); # jednostr. spektrum
jednostr_spektrum(2:end-1) = 2 * jednostr_spektrum(2:end-1); # úprava amplitudy
fft_signalu_jednostr = fft_signalu(1:poc_bodu_sign/2+1);   #jednostr. komplexní


# Frekvenční vektor
f_vektor = Fvzorkovani*(0:(poc_bodu_sign/2))/poc_bodu_sign;





# Identifikace dominantních frekvencí, prej jsou > 10%, ale tady je 30%
praach = 0.3 * max(jednostr_spektrum); % nastavení prahu pro identifikaci

# najít vrcholy:
[s_picky, ind_s_picek] = findpeaks(jednostr_spektrum, 'MinPeakHeight', praach);

index_zakl_harm = ind_s_picek(1);


zakladni_frekvence = f_vektor(index_zakl_harm); # základní frekvence


# výpočet počtu kmitů tady, sedí líp pro hodně zkreslené signály,
# pro ně se bude víc lišit od kmity_z_fun
pockmitu = zakladni_frekvence * Trvani_signalu;

if ~ isempty(kmity_z_fun)
  if (kmity_z_fun > 1) & (abs(pockmitu - kmity_z_fun) < 1)
    pockmitu = kmity_z_fun;
  end
endif





# amplituuda základní harmonické
zakl_harmonicka = jednostr_spektrum(index_zakl_harm);

#ss složka
ss_slozka = jednostr_spektrum(1);


# Výpočet z ostatních harmonických
% obsažené vyšší harmonické:
Indexy_harmonickych = 2:(floor(poc_bodu_sign/2/index_zakl_harm));
Indexy_harmonickych = Indexy_harmonickych .* (index_zakl_harm-1)+1;


souc_harm_na2 = sum(jednostr_spektrum(Indexy_harmonickych).^2);

# Výpočet THD v %
THD = 100 * sqrt(souc_harm_na2) / zakl_harmonicka;


#konec výpočtu FFT ////////////////////////////////////////////////////////////
endfunction#....................................................................












#*******************************************************************************
#*************Hl. program jako fuňkce qůli volání z menu************************
function [Cestafile, Jmfile, pocfile, hgrf1, hgrf2] = VypDFT (Cestafile, ...
          Jmfile, hgrf1, hgrf2, men, Velpis, pocfile, VolitFile, JenPrekres, Jedojpg);

#POZOR: pokud se dá VolitFile = true a filé bude zvoleno (= vybráno a pou žito)
#       bude programem nastavena proměnnná JenPrekres na false, aby se změny
#       provedly. (Nezáleží tedy na její hodnotě při vstupu do fuňkce.)



global ZpracDat VsechnyVybery;
global AmplHarmV;

global Fsmik RadBTfiltru JeBTfiltr;

global Osciloskop OscHAN OscOWO;
global plknastpod;
global PocKresHarm PocPocHarm PocHarm FposlHarm Fvypis FpocTHD;
global VerzeProg;
global JednHlWosyX JednHlWosyY JednWY;

global hfig1 HlavPlk;




persistent  THD  ss_slozka  pockmitu  index_zakl_harm  f_vektor;
persistent  jednostr_spektrum  fft_signalu_jednostr Indexy_harm;
persistent  OknoBlack  signBlack  thdnufBlack  jednostr_spektrum_black;
persistent  Indprvmax  Indposmax  kmity_z_fun;

persistent  Popisfile;

persistent  THDF jednostr_spektrumF signalsmik THDZadPoc;
persistent  KresSmikHarm PrubButter KresPrubBT;

persistent  procint IndVypis;





if  VolitFile


  if length(Cestafile) == 0
    Cestafile = pwd();     #nynější pracovní adresář
  else
    #zkusiti, jestli oná cesta ještě je
    if exist(Cestafile,'dir') ~= 7;    #dyš vrátí 7 tak je to adresář
      Cestafile = pwd();     #nejni, tak dát nynější pracovní adresář
    endif
  endif




  # dobrý popis uuuiiigetfilé je na (sice pro matlab...)
  #   https://uk.mathworks.com/help/matlab/ref/uigetfile.html



  if compare_versions(version, '10.2.0','==')
     # takle to chodilo ve verzi oktáávy 10.2.0 a jeto v ní potřeba, jinak
     # uíígetfilé po spuštění oktávy občas předvolí adresář prostředí oktávy
     # a NÉÉ ten, co tomu posílám v Cestafile....
     [Jmfile, Cestafilevyb, pocfile] = uigetfile ({'*.csv';'*.txt'},...
                     "Choose input file (csv or txt)", cstrcat(Cestafile,'\'));
  else
     # a takle to chodí ve verzi oktáávy 10.3.0, preparát je to i pro jiné verze
     [Jmfile, Cestafilevyb, pocfile] = uigetfile ({'*.csv';'*.txt'},...
                     "Choose input file (csv or txt)", cstrcat(Cestafile));

  endif



  if pocfile < 1;
    odp = msgbox('No file has been selected, you can select it from the menu later.' , 'Choosing file');
    return;       #ve fuňkci je východ takto
  else
    Cestafile = fullfile(Cestafilevyb);
  endif

  JenPrekres = false; # je nové filé => překreslit

  set(gcf, 'pointer', 'watch');  #čekatiti''''''''''''''''''''''''''''''''''''''

endif




if isempty(Jmfile);
  set (gcf, 'pointer', 'arrow');  #ne čekatiti''''''''''''''''''''''''''''''''''
  return;
endif



JmfilesCest = fullfile(Cestafile,Jmfile);


Plk = cstrcat(HlavPlk, ' for file:   ', Jmfile);  #tady stačí jen méno filé
set(hfig1, 'name', Plk);




bota = false;
try
  datata = importdata (JmfilesCest);  # takto to (snad) načte jedle pro různé
                                      # palice, tedy pro HANTEK i PRO OWOUN
                                      # ale pro OWOUN jedle jen pro záznam
                                      # jednoho kanálu
catch
  bota= true;
end_try_catch


if bota
  bota = false;
  try
    datata = importdata (JmfilesCest, ',',22); # takto to (snad) načte jedle pro
                         # dvoukanálový záznam OWOUN, ale taky pro simulaci
    if Cmuchret(datata.textdata{1}, 'Model,ADS802A') == 0
      bota= true;
    endif

  catch
    bota= true;
  end_try_catch
endif





if bota
  # záznam OWOUN nebo HANTEK filé to nejni, jestli to nejni simulace

  bota=false;
  try
    datata = importdata (JmfilesCest,',');
  catch
    bota= true;
  end_try_catch
endif




Osciloskop = "";
if bota == false
  if length(datata.textdata) == 3
    # Hantek, má jen 3 řádky palice
    Osciloskop = OscHAN;
  elseif length(datata.textdata) == 22
    # OWOUN má 22 řádků palice
    Osciloskop = OscOWO;
  endif
endif


if length(Osciloskop) == 0;
   plk = cstrcat('Selected file does not correspond to either of two,',newline );
   plk = cstrcat(plk, 'oscilloscopes, whose files this program can read.',newline);
   plk = cstrcat(plk, '( ',OscHAN,' a ', OscOWO, ' )',newline);
   plk = cstrcat(plk, 'You can select file from the menu later.',newline);
   odp = msgbox(plk , 'Choosing file');

   set(gcf, 'pointer', 'arrow');  #nečekatiti'''''''''''''''''''''''''''''''''''
   return;
endif




# Vytažení signálu a casování ze sloupců v .data:

PlkyOsc = datata.textdata;   # je to muňkové pole
RozsachOscProKan(1) = 0;     # první obsazení, nula by nikdy být nemělo
RozsachOsc = 0;              # první obsazení, nula by nikdy být nemělo
JeSimulace = false;       # jestli data jsou ze simulace (výpočtu) nebo z měření
bityAD = 0;                  # simulovaný počet bitů AD převodníku






CislaKanalu = 1;      # u Hantek dycky 1, kanalízace tam ve výpise nejsou
KanalyVeFileVse = '1';
MaxPocKanalu = 10;  # snad bude 10 stačit
KanalyVeFilePole = cell(1,MaxPocKanalu);
KanalyVeFilePole{1} = KanalyVeFileVse;
JednVeFilePole = cell(1,MaxPocKanalu);
JednVeFilePole{1} = KanalyVeFileVse;
OsciloskopModel = '';

JednHlWosyX = 'Time [';        #přednastavení pro nové filé, dyby tam nebylo
JednHlWosyY = 'Amplitude [';  #ale tady bez jednotek, doplní se dáále
JednWY = 'V';                 #natwrrdo jednotky wosy Y



# čtení palice osciloskopu Hantek **********************************************
if Cmuchret(Osciloskop, OscHAN) > 0
  OsciloskopModel = OscHAN;

  for i = 1:length(PlkyOsc);

    Jeprekodovani = false;
    PlkOscUTF8 = sprintf('%c', unicode2native(PlkyOsc{i}, 'cp1250'));
    if Cmuchret(PlkOscUTF8, ',#voltbase=') > 0
      try
        RozsachOscProKan(1) = str2double(regexp(PlkOscUTF8, ...
                   '[-+]?\d*\.?\d+([eE][-+]?\d+)?', 'match', 'once'));
        Jeprekodovani = true;
      catch
        RozsachOscProKan(1) = str2double(regexp(PlkyOsc{i}, ...
                   '[-+]?\d*\.?\d+([eE][-+]?\d+)?', 'match', 'once'));
        Jeprekodovani = false;
      end
      PozRoz = i;
      break;
    endif
  endfor

  if RozsachOscProKan(1) > 0
     if Jeprekodovani
       PlkOscUTF8 = sprintf('%c', unicode2native(PlkyOsc{PozRoz}, 'cp1250'));
       Cmuchplk = 'simulated';
     else
       PlkOscUTF8 = PlkyOsc{PozRoz};
       Cmuchplk = 'simulated';
     endif
     if Cmuchret(PlkOscUTF8, Cmuchplk) > 0
       # je simulace
       Hausnumera = str2double(regexp(PlkOscUTF8,...
                    '[-+]?\d*\.?\d+([eE][-+]?\d+)?', 'match'));
       JeSimulace = true;
       if length(Hausnumera) >= 3
         #je simulováno qantování podle bitů AD převodníku
         RozsachOscProKan (1) = Hausnumera(3);
         bityAD = Hausnumera(2);
       endif
     else
       # převod ze setin mV Hanteku na V:
       RozsachOscProKan(1) = RozsachOscProKan(1) * 1e-5;
     endif
  endif
endif



# čtení palice osciloskopú OWOUN ***********************************************
UzJeObs = 0;  # spočtení kolík oných obsadilo, zatím se dáál nepoužívá
if Cmuchret(Osciloskop, OscOWO) > 0
  for i = 1:length(PlkyOsc);
    PlkOscUTF8 = PlkyOsc{i};


    if Cmuchret(PlkOscUTF8, 'Model,') > 0
      #přečtení modelu osciloskopu ********************************************
      OsciloskopModel = cstrcat('OWON ',PlkOscUTF8(Cmuchret(PlkOscUTF8, ',')+1:end));
      UzJeObs = UzJeObs + 1;
    endif


    if Cmuchret(PlkOscUTF8, 'vertical Scale,') > 0
      #přečtení vertikálního rozsahu ******************************************

      RozsachOscProKan = str2double(regexp(PlkOscUTF8, ...
                                    '[-+]?\d*\.?\d+([eE][-+]?\d+)?', 'match'));


      for i = 1:length(RozsachOscProKan);
        #můžou být volty nebo mV nebo μV a nic jinšího ?? - byl by rozsach = 0!!
        Nasrozs(i) = 0;
        if Cmuchret(PlkOscUTF8(Cmuchret(PlkOscUTF8, ',')+1:length(PlkOscUTF8)),'mV') > 0
          # mV musí být dříf, páč V je tam taky
          Nasrozs(i) = 0.001;     #násobitel na V z mV
        elseif Cmuchret(PlkOscUTF8(Cmuchret(PlkOscUTF8, ',')+1:length(PlkOscUTF8)),'μV') > 0
          # μV musí být dříf, páč V je tam taky
          Nasrozs(i) = 0.000001;  #násobitel na V z μV
        elseif Cmuchret(PlkOscUTF8(Cmuchret(PlkOscUTF8, ',')+1:length(PlkOscUTF8)),'V') > 0
          Nasrozs(i) = 1;         #násobitel na V z V
        endif
        #stínítko má 8 dílků:
        RozsachOscProKan(i) = RozsachOscProKan(i) * 8 * Nasrozs(i);
      endfor
      UzJeObs = UzJeObs + 1;
    endif


    if Cmuchret(PlkOscUTF8, 'Channel,') > 0
      #přečtení počtu zaznamenaných kanalizací ********************************

      CislaKanalu = str2double(regexp(PlkOscUTF8, ...
                 '[-+]?\d*\.?\d+([eE][-+]?\d+)?', 'match'));

      KanalyVeFileVse = PlkOscUTF8(Cmuchret(PlkOscUTF8, ',')+1:end);
      KanalyVeFile = KanalyVeFileVse;

      Carka =  Cmuchret(KanalyVeFile,",");
      i = 1;
      if Carka > 0
        KanalyVeFilePole{i} = KanalyVeFile(1:Carka-1);
        do
          i= i + 1;
          if i > 10   # podle deklarace pole KanalyVeFilePole(1,x)
            break;
          endif
          KanalyVeFile = KanalyVeFile(Carka+1:end);
          Carka = Cmuchret(KanalyVeFile,",");
          if Carka > 0
            KanalyVeFilePole{i} = KanalyVeFile(1:Carka-1);
          else
            KanalyVeFilePole{i} = KanalyVeFile;
          endif
        until (Carka == 0) | (Carka == length(KanalyVeFile))
      else
        KanalyVeFilePole{i} = KanalyVeFile;
      endif
      UzJeObs = UzJeObs + 1;
    endif


    if Cmuchret(PlkOscUTF8, '(Units:') > 0
      #přečtení jednotek zaznamenaných dat ************************************

      JednVeFileVse = PlkOscUTF8;
      JednVeFile = JednVeFileVse;

      Carka =  Cmuchret(JednVeFile,",");
      i = 1;
      if Carka > 0
        JednVeFilePole{i} = JednVeFile(1:Carka-1);
        do
          i= i + 1;
          if i > 10   # podle deklarace pole JednVeFilePole(1,x)
            break;
          endif
          JednVeFile = JednVeFile(Carka+1:end);
          Carka = Cmuchret(JednVeFile,",");
          if Carka > 0
            JednVeFilePole{i} = JednVeFile(1:Carka-1);
          else
            JednVeFilePole{i} = JednVeFile;
          endif
        until (Carka == 0) | (Carka == length(JednVeFile))
      else
        JednVeFilePole{i} = JednVeFile;
      endif
      UzJeObs = UzJeObs + 1;
    endif


  endfor
endif





ZprcKanal = 1;
RozsachOsc = RozsachOscProKan(1);
if length(CislaKanalu) > 1
  #je víc kana lízací, dát dotas kterou zpracovat

  CelkPocKan = length(CislaKanalu);
  plk = cstrcat('In processed file:' ...
      ,newline, '   ', JmfilesCest...
      ,newline, 'are channels    ',KanalyVeFileVse ...
      ,'    in total ', num2str(CelkPocKan,'%d'), ' channels.'...
      ,newline, 'Enter channel number (without CH, just number),'...
      ,' that will be processed from this list.'...
      ,newline, newline, 'If you enter a value that is not in channel list,'...
      ,' FIRST CHANNEL LISTED will be processed.'...
      , newline, 'When there are more channels in file than ',num2str(MaxPocKanalu,'%d')...
      ,' (which I do not expect), only first '...
      ,num2str(MaxPocKanalu,'%d'),' channels are listed here.', newline);



  plktit = 'Entering of measured channel for processing.';
  defaults = {CislaKanalu(1)};
  rowscols = [1,5];
  vlozeno = inputdlg (plk ,plktit ,rowscols , defaults);

  if isempty(vlozeno)
    #vstup byl zrušen
    ZprcKanal = 1;

  elseif (unicode2native(upper(strtrim(vlozeno{1}))(1:1))<48) | ...
         (unicode2native(upper(strtrim(vlozeno{1}))(1:1))>57)
    #první znak nejni čííslo
    ZprcKanal = 1;

  else
    ZprcKanal = fix(str2double(vlozeno{1}));  #číslo zprc. kanálu
    if (ZprcKanal < CislaKanalu(1)) | (ZprcKanal > CislaKanalu(length(CislaKanalu)))
      ZprcKanal = 1;
    else
      Priradilo = false;
      for i = 1:length(CislaKanalu);
        if CislaKanalu(i) == ZprcKanal
          ZprcKanal = i;    #toto je pořadí oného v poli CislaKanalu
          Priradilo = true;
          break;            #výskok z Do, While nebo For smyček
        endif
      endfor
      if ~ Priradilo  # to je NOT Priradilo
        ZprcKanal = 1;
      endif
    endif
    RozsachOsc = RozsachOscProKan(ZprcKanal);
  endif
endif


signal = datata.data(:,ZprcKanal+1);
casovaniOsc = datata.data(:,1);



if strcmp(Osciloskop, OscOWO)
  # doplnění jednotek do popisu wos hl. gřafu podle filé

  PorDwojtecky = Cmuchret(JednVeFilePole{1},':');
  JednWY = JednVeFilePole{1}(PorDwojtecky + 1:PorDwojtecky + 1);
  if Cmuchret(upper(JednWY), 'S') > 0
    JednHlWosyX = cstrcat(JednHlWosyX, 'seconds]');
  else
    JednHlWosyX = cstrcat(JednHlWosyX, JednWY, ']');
  endif

  PorDwojtecky = Cmuchret(JednVeFilePole{ZprcKanal+1},':');
  JednWY = JednVeFilePole{ZprcKanal+1}(PorDwojtecky+1:PorDwojtecky+1);
  JednHlWosyY = cstrcat(JednHlWosyY, JednWY, ']');
else
  # doplnění jednotek do popisu wos hl. gřafu natwrdo

  JednHlWosyX = cstrcat(JednHlWosyX, 'seconds]');
  JednHlWosyY = cstrcat(JednHlWosyY, 'V]');
  JednWY = 'V';
endif




CasKrok = casovaniOsc(2)-casovaniOsc(1);   %v sevteřinách
Fvzorkovani = 1/CasKrok;                   %kmitočet vzorkování


if strcmp(Osciloskop, OscHAN)
  # osciloskop hantek
  casovani(1,:) = 0;
  for i = 2:length(signal);
    casovani(i,:) = casovani(i - 1,:) + CasKrok;
  endfor;

elseif strcmp(Osciloskop, OscOWO)
  # osciloskop OWOUN - jeho časování má nulu u prostřed, takže použití
  #      úpravy pro hantek i pro OWOUN to udělá od nuly...
  casovani = casovaniOsc;
endif







if ~ JenPrekres#---------------------------------------------------------------


  #zjištění, jeli možnost použíti všechny výběry pro zpracování filé

  #zmenšit na miminální velikost řekněme 2048 dat
  vel_cel_sig = length(signal);
  koesmik = 2048 / vel_cel_sig;
  VsechnyVybery = false;

  if koesmik < 1
    #redukovat

    redukrok = fix(vel_cel_sig / (vel_cel_sig * koesmik));
    redukovany_signal = signal(1:redukrok:end); % každá redukrok hodnota

    if abs(max(redukovany_signal)) == 0
      # BOTA!!!!!!!!!
      plk = cstrcat('When processing the file:' ...
        ,newline, '   ', JmfilesCest...
        ,newline, 'bug occurred (the reduced signal contains only zeros)!!'...
        ,newline,newline, 'This file cannot be processed at this time; it probably does not' ...
        ,newline, 'have a suitable waveform (pulses, rectangle, etc.) for processing...' ...
        ,newline, newline, 'After closing this warning, the program will be TERMINATED !!');

      plktit = 'PROCESSING ERROR';
      handlplk = msgbox(plk , plktit, 'modal');
      uiwait(handlplk);     # čeká na zavření

      close all;            # smaže fšecky figůůry => ukončí i program
    endif

    redukovane_casovani = casovani(1:redukrok:end);
    Fvzred = 1/(redukovane_casovani(2)-redukovane_casovani(1));

    [THDred , ~, pockmitured, ~, ~, ~, ~, ~] = FFTNufsTHD (redukovany_signal, Fvzred, []);

  else
    #je málo dat, redukce nemá smysl, THD spočítat z celého signálu

    [THDred , ~, pockmitured, ~, ~, ~, ~, ~] = FFTNufsTHD (signal, Fvzorkovani, []);
  end

  if THDred < 25  #jen při takovém THD mají výběry průběhů smysl, jinak kecají
    if pockmitured > 2  #a jen dyš je víc kmitů jak aspoň 2
      if (vel_cel_sig / pockmitured) > 300
      #a jen dyš je víc jak 300 bodů na kmit, jinak neumí jedle vybrat začátky
        VsechnyVybery = true;
      endif
    endif
  endif







  #určení, jak se bude filé zpracovávati
  if ~ VsechnyVybery     #to je (if not VsechnyVybery)
    # jenom celé filé
    ZpracDat = 4;

    if ~ isempty(men)
      #znepřístupnění ostatních výběrů, kromě celého filé
      set (men.nastpod(1), "enable", 'off');
      set (men.nastpod(2), "enable", 'off');
      set (men.nastpod(3), "enable", 'off');

      set (men.nastpod(1), "checked", 'off');
      set (men.nastpod(2), "checked", 'off');
      set (men.nastpod(3), "checked", 'off');
      set (men.nastpod(4), "checked", 'on');

      set (men.nastpod(1), "text", cstrcat('NOT POSSIBLE - ', plknastpod{1}));
      set (men.nastpod(2), "text", cstrcat('NOT POSSIBLE - ', plknastpod{2}));
      set (men.nastpod(3), "text", cstrcat('NOT POSSIBLE - ', plknastpod{3}));
    endif

  else
    #zpřístupňění fšech výběrů
    if ~ isempty(men)
      for i = 1: length(men.nastpod)
        set(men.nastpod(i), "enable", 'on')
        set (men.nastpod(i), "text", cstrcat(plknastpod{i}));
      endfor
    endif

  endif


  kmity_z_fun = -999;
  switch ZpracDat

    case (1)
      #nastavení na celé kmity od nuly \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
      [Indprvmax, Indposmax, kmity_z_fun]=UprnaPruchNulou (signal, Fvzorkovani);

    case(2)
      #nastavení na celé kmity zhruba od maxima \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
      [Indprvmax, Indposmax, kmity_z_fun]=UprnaCeleodMax (signal, Fvzorkovani);

    case(3)
      #nastavení na celé kmity od začátku filé \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
      [Indprvmax, Indposmax, kmity_z_fun]=UprnaCeleodZac (signal, Fvzorkovani);

    case(4)
      #pro celé filé
      [Indprvmax, Indposmax, kmity_z_fun] = UprnaCeleFile (signal, Fvzorkovani);

  endswitch

endif#--------------------------------------------------------------------------



#a přestavení podle zvoleného intervalu
signalcast = signal(Indprvmax:Indposmax);
casovanicast = casovani(Indprvmax:Indposmax);














#-------------------------------------------------------------------------------
# nakreslení změřených dat ve vybraném intervalu -------------------------------


### nastavení figure 1, je v hl programu !!!!!!!!!!!!!!!!!!!!!!!!!!!!



# v příkazu subplot je pozice VŽDY normována mezi 0 a 1!!!!!
hgrf1 = subplot("position",[0.05,0.57,0.9,0.38]);  #[x, y, width, height]

plot(casovanicast, signalcast, 'linewidth', 0.4);




set (gca, 'fontsize', Velpis)                 %velikost písma v oném gřafu
set (gca, "xminortick", "on", "yminortick", "on");
set (gca, "xgrid", "on","ygrid", "on");
set (gca, "gridcolor","black");
#"-" plná, "--" čárk., ":" tečk., "-." čerch., "" nic:
set (gca, "gridlinestyle", "-");
grid minor on;
grid on;
ti_tulek = cstrcat('Measured data from file: ', JmfilesCest);


# z IÁÁ: Octave (při vykreslování textu v grafech) interpretuje určité znaky
#        jako formátovací sekvence pro subscripts/superscripts. Podtržítko "_"
#        je v Octave/gnuplot/Qt interpre­továno jako začátek dolního indexu.
#        Takže aby se zobrazilo jedle vypnout interpretaci formátování.
title(ti_tulek,'Interpreter','none');


xlabel(hgrf1 , JednHlWosyX);
ylabel(hgrf1, JednHlWosyY);
hold on # udržení gřafu pro další kreslení do něj




Efhodn = rms(signalcast);  #efektivní hovnota, RMS - root mean square






if ~ JenPrekres#---------------------------------------------------------------
  #je to: if NOT JenPrekres

  # Výpočty THD a Fourierovy transformace //////////////////////////////////////


  [THD, ss_slozka, pockmitu, index_zakl_harm, f_vektor, jednostr_spektrum, ...
          fft_signalu_jednostr, Indexy_harm] = FFTNufsTHD (signalcast, ...
          Fvzorkovani, kmity_z_fun);


  PocHarm = length(Indexy_harm);

  FposlHarm = f_vektor(Indexy_harm(PocHarm));



  if PocHarm < PocPocHarm
    PocPocHarm = PocHarm;
  endif

  THDZadPoc = 100 * sqrt(sumsq(jednostr_spektrum(Indexy_harm(1:PocPocHarm))))...
              / jednostr_spektrum(index_zakl_harm)


  if PocHarm < PocKresHarm
    PocKresHarm = PocHarm;
  endif
  IndVypis = round(Indexy_harm(PocKresHarm));
  procint = (PocKresHarm/PocHarm) * 100;
  Fvypis = round( f_vektor(IndVypis));
  FpocTHD = round(f_vektor(round(Indexy_harm(PocPocHarm))));

  if ~ isempty(men)
  # změnit taky plky v menu pro zadání počtu kreslených počítaných harmounických
    plk = cstrcat("Change in number of plotted harmonics ");
    plk = cstrcat(plk, '(now it is ',num2str(PocKresHarm, "%d"), ' i.e. up to ');
    plk = cstrcat(plk, num2str(sigfig(Fvypis/1000,4)),' kHz)');
    set (men.nastPocHarm, 'text' , plk);
    set (men.kontmenu.nastPocHarm, 'text' , plk);


    plk = cstrcat("Change in last calculated harmonics ");
    plk = cstrcat(plk, '(now it is ',num2str(PocPocHarm + 1, "%d"), '. i.e. up to ');
    plk = cstrcat(plk, num2str(sigfig(FpocTHD/1000,4)),' kHz)');
    set (men.nastPocPocHarm, 'text' , plk);
    set (men.kontmenu.nastPocPocHarm, 'text' , plk);
  endif





  KresPrubBT = false;
  KresSmikHarm = false;
  if JeBTfiltr

    signalsmik = DPButerworth (RadBTfiltru, signalcast, Fvzorkovani, Fsmik);


    [THDF, ~, ~, ~, ~, jednostr_spektrumF, ...
             ~, Indexy_harmF] = FFTNufsTHD (signalsmik, Fvzorkovani, kmity_z_fun);



    Fnorm = Fsmik/(Fvzorkovani/2);

    if (Fnorm <= 1) && (Fnorm >= 0);  #zdvojení operátoru na && je zkratka

      % Výpočet frekvenční odezvy Butterwortha, PrubButter je kompleksní
      [b, a] = butter(RadBTfiltru, Fsmik/(Fvzorkovani/2), 'low');
      [PrubButter, we] = freqz(b, a, f_vektor, Fvzorkovani);

      KresPrubBT = true;

    endif





    #kresliti když je průběh harmonických přes filtr Butterworth aspoň trochu
    #jiný než průběh harmonických bez filtru, páč dyš se blíží nebo je stejné
    #tak kreslení průběhu přes filtr přerazí průběh bez filtru a vypadá to,
    #jakodyby tam nebyl...
    KresSmikHarm = false;

    prumkrfilt = mean(jednostr_spektrumF(1:IndVypis));
    prumkr = mean(jednostr_spektrum(1:IndVypis));
    if abs(1 - prumkrfilt/prumkr) * 100 >= 1  #rozdíl v %
        KresSmikHarm = true;
    endif
  endif






  #.............................................................................
  #výpočet THD pro vstupní signál přes Blackmanovo okno (jako příklad)


  poc_bodu_sign = length(signalcast);

  #výpočet koe ficyjentů wokenic
  OknoBlack = blackman(poc_bodu_sign);

  #přepočet fft koe fycyjentama wokenic
  #s tečkou (.*) je to násobení element * element, BEZ (jen *) MATICOVÉ
  signBlack = signalcast .* OknoBlack;
  [thdnufBlack, ~, ~, ~, ~, jednostr_spektrum_black, ~, ~] = FFTNufsTHD ...
                                  (signBlack, Fvzorkovani, kmity_z_fun);



#konec výpočtů FFT ////////////////////////////////////////////////////////////

endif#--------------------------------------------------------------------------










plot(casovanicast, signBlack, 'linewidth', 0.4, 'linestyle', ':', 'color','black');


# přidání legendy+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hlegendy = legend('measured data' , 'meas. data via Blackmann window');


set(hlegendy, 'Box', 'off');  # vypnout rámeček a možná i pozadí


if ~ Jedojpg
  # výstup na vobra žofku
  set(hlegendy, 'fontsize', Velpis*1.04); # 0.97);
else
  # výstup do obrazového filé
  set(hlegendy, 'fontsize', Velpis*0.95);
endif

# nastavení pozice legendy relativně k X wose:
nastavPozLegendyRelatkOse(gca, hlegendy, getappdata(gcf,'RelPosLegHL'));
drawnow;

# uložení do appdat figúry potřebných handlů pro HL gřaf
setappdata(gcf, "hLegHL", hlegendy);
setappdata(gcf, "hOsyXHL", gca);


hold off;  #zrušení udržení pro další kreslení
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


VobsadDilkyWos (hgrf1, min(casovanicast), max(casovanicast),"X");
VobsadDilkyWos (hgrf1, min(signalcast), max(signalcast),"Y");











if VolitFile#---------------------------------------------------------------
  #vymazání starého gřafu harmonických, aby tam při dotazu nesmrďéél:
  delete(hgrf2);

  plk = cstrcat('Enter a description (identification) of processed file:');
  PopisfileVst = inputdlg (plk ,'Entering description of this calculation',[1,60], {Popisfile});

  if length(PopisfileVst)>0
    Popisfile = PopisfileVst{1};
  else
    if length(Popisfile)==0
      Popisfile = "";
    endif
  end
end #--------------------------------------------------------------------------









#přidání plkú @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#jsou umísťovány v souřadnicích prvního obrázku, musí být za ním





krajeos = axis();  #krajní body os gřafu
odstrad = 0.05;    #odstup řádků v násobiteli y souřadnice
prvrad = 0.15;     #první řádek v násobiteli y souřadnice qůli nyqvistovi
tabnuf = 0.25;     #něco jako tabulátor - posunuje plk
pocharvyp = 10;    #počet harmonických na výpis
pocplatcislic = 5; #počet platných číslic ve výpise



# trochu posun plků do leva qůli jejich šířce, MUSÍ být uděláno jako poměr
# rozsahů x, páč krajeos(2) se u každého kreslení jaksi mění, čert ví proč..
krajeos(1) = krajeos(1) - 0.015*(krajeos(2)-krajeos(1));



# první řádek
radek = 0;         #číslo vystupovaného řádku (první řádek je 0)

#násl. príkazy text vystoupí text do aktivní figury, v souřadnicích
#os právě kresleného gřafu


plk = cstrcat(Popisfile);
# prvrad-0.01 je zvýšení popisu aby byl trochu oddělen aspoň mizerou
# dyš tu nejde podtržení
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad-0.01+odstrad*radek), ...
      plk, 'fontsize', Velpis, 'fontweight', 'bold');


radek++;
if JeSimulace
  plk = cstrcat('Calculation of harmonic distortion (THD) for {\bfsimulated signal}:');
else
  if strcmp(Osciloskop, OscOWO)
    plk = cstrcat('Calculation of harmonic distortion (THD) for oscilloscope ','{\bf',OsciloskopModel,'}:');
  else
    plk = cstrcat('Calculation of harmonic distortion (THD) for ','{\bf',OsciloskopModel,'}',' oscilloscope data type:');
  endif
endif
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);






radek++;
plk = cstrcat('File is processed from record ', num2str(Indprvmax, "%d"),...
      ' do ',num2str(round(Indposmax), "%d"), ' and has in total ',...
      num2str(length(signal), "%7.0i"),' records.');
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);




radek++;
plk = cstrcat('Highest usable F (Nyquist) is ');
plk = cstrcat(plk, num2str(sigfig(Fvzorkovani/2000,4), Formnamista(Fvzorkovani/2000,4)), ' kHz');
if JeSimulace
  if bityAD <= 0
     plk = cstrcat(plk, ', is simulation with max. resolution.');
  else
     plk = cstrcat(plk, ', is simulation ');
     plk = cstrcat(plk, num2str(bityAD, "%d"), ' bits from ');
     plk = cstrcat(plk, num2str(RozsachOsc, "%d"), ' V.');
  endif
else
  plk = cstrcat(plk, ', oscilloscope range ');
  plk = cstrcat(plk, num2str(RozsachOsc, "%d"), ' V');
  if strcmp(Osciloskop, OscOWO)
    plk = cstrcat(plk, ', channel ', KanalyVeFilePole{ZprcKanal});
  endif
endif
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);


radek++;
switch ZpracDat
  case 1
    plk = cstrcat('Whole cycles from first zero crossing are processed; ');
  case 2
    plk = cstrcat('Whole cycles from first maximum are processed; ');
  case 3
    plk = cstrcat('Whole cycles from beginning of file are processed; ');
  case 4
    plk = cstrcat('Entire file is processed; ');
endswitch
plk = cstrcat('{\bf', plk ,'}');   #tučný výstup plku



if (pockmitu == 1)
  #plkzac = 'Je zpracován ';
  plkzac = 'total ';
  plkkon = ' cycle.';
elseif ((pockmitu > 1) & (pockmitu < 5))  # & je and
  plkzac = 'total ';
  plkkon = ' cycles.';
else
  plkzac = 'total ';
  plkkon = ' cycles.';
endif
plk = cstrcat(plk,' ', plkzac, num2str(pockmitu, "%d"),plkkon);
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);










radek++;radek++;
plk = cstrcat('Effective value (RMS) of full processed signal:');
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
plk = cstrcat(num2str(sigfig(Efhodn,pocplatcislic), Formnamista(Efhodn,pocplatcislic)), ' ',JednWY,'rms');
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);



radek++;
plk = cstrcat('Direct current component:');
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
plk = cstrcat(num2str(sigfig(ss_slozka,pocplatcislic), Formnamista(ss_slozka,pocplatcislic)), ' ', JednWY);
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);



radek++;
plk = cstrcat('THD full proces. signal up to ',num2str(sigfig(PocHarm + 1,8)),'th harm., ',num2str(sigfig(FposlHarm/1000,4)),' kHz:');
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
plk = cstrcat(num2str(sigfig(THD,pocplatcislic), Formnamista(THD,pocplatcislic)), ' %');
if sigfig(THD, pocplatcislic) <= sigfig(thdnufBlack, pocplatcislic)
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis, 'fontweight', 'bold');
else
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
endif



radek++;
plk = cstrcat('THD full proces. signal through Blackman window:');
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
plk = cstrcat(num2str(sigfig(thdnufBlack,pocplatcislic), Formnamista(thdnufBlack,pocplatcislic)), ' %');
if sigfig(THD, pocplatcislic) >= sigfig(thdnufBlack, pocplatcislic)
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis, 'fontweight', 'bold');
else
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
endif




if JeBTfiltr
  radek++;
  plk = cstrcat(' THD through order ',num2str(sigfig(RadBTfiltru,8)),' Butterworth LP filter, Fo ',num2str(sigfig(Fsmik/1000,4)),' kHz:');
  text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
  plk = cstrcat(num2str(sigfig(THDF,pocplatcislic), Formnamista(THDF,pocplatcislic)), ' %');
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
endif



radek++;
plk = cstrcat(' THD calc. from 2nd to ',num2str(PocPocHarm + 1,"%d"));
if PocPocHarm == 2
  plk = cstrcat(plk, 'rd harmonic ');
else
  plk = cstrcat(plk, 'th harmonics ');
endif
plk = cstrcat(plk, '(up to ',num2str(sigfig(FpocTHD/1000,4)),' kHz):');
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);
plk = cstrcat(num2str(sigfig(THDZadPoc,pocplatcislic), Formnamista(THDZadPoc,pocplatcislic)), ' %');
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis);







radek++;radek++;
plk = cstrcat('{\bfList of harmonics} (here only up to ',num2str(pocharvyp,"%d"),'. harmonics):');
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis)  #, 'fontweight', 'bold');




tabnuf1 = 0.1;
tabnuf2 = 0.175;
tabnuf3 = 0.25;





radek++;
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf1,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), 'Frequency', 'fontsize', Velpis, 'fontweight', 'bold');
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf2,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), 'Amplitude', 'fontsize', Velpis, 'fontweight', 'bold');
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf3,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), 'Phase' , 'fontsize', Velpis, 'fontweight', 'bold');






radek++;
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), 'Primary harmonic:', 'fontsize',Velpis);
# freqence
plk = cstrcat(num2str(sigfig(f_vektor(index_zakl_harm),pocplatcislic), Formnamista(f_vektor(index_zakl_harm),pocplatcislic)), ' Hz');
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf1,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis)
# ampli túúda
plk = cstrcat(num2str(sigfig(jednostr_spektrum(index_zakl_harm),pocplatcislic), Formnamista(jednostr_spektrum(index_zakl_harm),pocplatcislic)),' ',JednWY);
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf2,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis)
# fááze
fazev = faze(real(fft_signalu_jednostr(index_zakl_harm)), imag(fft_signalu_jednostr(index_zakl_harm)));
plk = cstrcat(num2str(sigfig(fazev, pocplatcislic),  Formnamista(fazev,pocplatcislic)), ' °');
text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf3,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk , 'fontsize', Velpis)








for i = 2:pocharvyp
  radek++;
  plk = cstrcat(num2str(i,"%d"),'. harmonic:');
  text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize',Velpis);
  # freqence
  plk = cstrcat(num2str(sigfig(f_vektor((index_zakl_harm-1)*i+1),pocplatcislic), Formnamista(f_vektor((index_zakl_harm-1)*i+1),pocplatcislic)), ' Hz');
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf1,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis)
  # ampli túúda
  plk = cstrcat(num2str(sigfig(jednostr_spektrum((index_zakl_harm-1)*i+1),pocplatcislic), Formnamista(jednostr_spektrum((index_zakl_harm-1)*i+1),pocplatcislic)),' ',JednWY);
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf2,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk, 'fontsize', Velpis)
  # fááze
  fazev = faze(real(fft_signalu_jednostr((index_zakl_harm-1)*i+1)), imag(fft_signalu_jednostr((index_zakl_harm-1)*i+1)));
  plk = cstrcat(num2str(sigfig(fazev, pocplatcislic), Formnamista(fazev,pocplatcislic)), ' °');
  text (krajeos(1) + (krajeos(2)-krajeos(1))*tabnuf3,krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek), plk , 'fontsize', Velpis)
endfor





radek++;
plk = '© Luděk Ruffer       lruffer@volny.cz';
plk = cstrcat(plk, '       program version dated ', VerzeProg);
# v příkazu color [r,g,b] se míchají světla: třeba 0,0,0, je černá..
# třeba [0, 0.35, 0.65] dál je tmafší modrá
text (krajeos(1),krajeos(3)-(krajeos(4)-krajeos(3))*(prvrad+odstrad*radek)*1.02, plk, 'fontsize', Velpis, 'color', [0, 0.35, 0.65]);













# 2. gřaf harmonických a Butterwortha!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


if Jedojpg
  #trochu výš a nižší, aby se pod oné vešla legenda pro DP Butterworth
  # v příkazu subplot je pozice VŽDY normována mezi 0 a 1!!!!!
  hgrf2 = subplot("position",[0.37,0.1,0.58,0.35]);  #[x, y, width, height]
else
  hgrf2 = subplot("position",[0.37,0.08,0.58,0.37]);
endif







# pro rozhodnutí o wosách (lineární - logaritmické) je rozhodující první
# kreslení, další do stejného gřafu už můžou být plotkem, drží to v tom případě
# vosy jak byly nakresleny po prvé...

if AmplHarmV > 0
  # ve V
  semilogy(f_vektor(1:IndVypis)/1000, abs(jednostr_spektrum(1:IndVypis)), 'linewidth', 0.4);
else
  # v dB
  jednostr_spektrum_dB = 20 * log10(jednostr_spektrum/jednostr_spektrum(index_zakl_harm));
  plot(f_vektor(1:IndVypis)/1000, (jednostr_spektrum_dB(1:IndVypis)), 'linewidth', 0.4);
end




set (gca, 'fontsize', Velpis)        %velikost písma v oném gřafu
set (gca, "xminortick", "on")
set (gca, "xgrid", "on","ygrid", "on");
set (gca, "gridcolor","black");
set (gca, "gridlinestyle", "-");

# vlastnost xlimmode MUSÍ být "auto"
set (gca, "xlimmode", "auto");
set (gca, "xlimitmethod", "tight");

grid minor on;
grid on;          #když je až po malé mřííži, udělá velký mřížkový čáry plný




plk = cstrcat('Calculated harmonics (plotted up to ',...
      num2str(sigfig(Fvypis/1000,4)),' kHz',', i.e. up to ', ...
      num2str(PocKresHarm + 1, '%d'),'. harmonic and ',...
      num2str(sigfig(procint,3), '%d'),'% of calculated interval).');
title(plk);




xlabel(hgrf2, 'Frequency [kHz]');

if AmplHarmV > 0
  ylabel(hgrf2, 'Amplitude [V]');
else
  ylabel(hgrf2, 'Amplitude [dB]');
end
hold on # udržení gřafu pro další kreslení do něj .............................





#přidání Blackmannna a harm. přes DP Butterworth, dyš se kreslí

barvaprubBT = [0.45, 0.2, 0.666];

if AmplHarmV > 0
  # ve V

  plot(f_vektor(1:IndVypis)/1000, abs(jednostr_spektrum_black(1:IndVypis)), ...
                    'linewidth', 0.5, 'linestyle', ':', 'color','black');

  if KresSmikHarm
    handlBT = semilogy(f_vektor(1:IndVypis)/1000, (jednostr_spektrumF(1:IndVypis)), ...
                   'linewidth', 0.35, 'linestyle', '-.', 'color','red');

    Ywosyrozs = ylim;  # zapamatování si rozsachu wosy y teď


    hlegendyBT = legend(handlBT, 'harmonics through Butterworth LP filter');

    if KresPrubBT
      hav = abs(PrubButter);  #prevod na vektor z kompleksu a ve V

      #přidání další proměnnné do legendy takto:
      plot(f_vektor(1:IndVypis)/1000, hav(1:IndVypis), ...
             'linewidth', 0.35, 'linestyle', '--', 'color', barvaprubBT,  ...
             "displayname", "characteristics of Butterworth LP filter");
    endif


    ylim(Ywosyrozs); # vrácení rozsahu wosy y na hodnoty před kreslením průběhu,
                     # aby ho průběh nezvětšoval

  endif


else
  # v dB

  jednostr_spektrum_black_dB = 20 * log10(jednostr_spektrum_black/jednostr_spektrum_black(index_zakl_harm));
  plot(f_vektor(1:IndVypis)/1000, (jednostr_spektrum_black_dB(1:IndVypis)), ...
                   'linewidth', 0.5, 'linestyle', ':', 'color','black');


  if KresSmikHarm

    jednostr_spektrum_F_dB = 20 * log10(jednostr_spektrumF/jednostr_spektrumF(index_zakl_harm));
    handlBT = plot(f_vektor(1:IndVypis)/1000, (jednostr_spektrum_F_dB(1:IndVypis)), ...
                   'linewidth', 0.35, 'linestyle', '--', 'color','red');

    Ywosyrozs = ylim;  # zapamatování si rozsachu wosy y teď


    hlegendyBT = legend(handlBT, 'harmonics through Butterworth LP filter');

    if KresPrubBT
      hav = 20*log10(abs(PrubButter));  #prevod na vektor z kompleksu a v dB

      #přidání další proměnnné do legendy takto:
      plot(f_vektor(1:IndVypis)/1000, hav(1:IndVypis), ...
             'linewidth', 0.35, 'linestyle', '--', 'color', barvaprubBT,
             "displayname", "characteristics of Butterworth LP filter");
    endif

    ylim(Ywosyrozs);  # vrácení rozsahu wosy y na hodnoty před kreslením průběhu,
                      # aby ho průběh nezvětšoval
  endif

end



# a nastavení legendy pro Butterwortha dyš je, jen jednou tu
if KresSmikHarm

    set(hlegendyBT, 'Box', 'off');
    if Jedojpg
      set(hlegendyBT, 'fontsize', Velpis*1.04); # 0.97);
    else
      set(hlegendyBT, 'fontsize', Velpis*0.97);
    endif

    nastavPozLegendyRelatkOse(gca, hlegendyBT, getappdata(gcf, 'RelPosLegBT'));
    drawnow;

    # uložení do appdat figúry potřebných handlů pro BT gřaf
    setappdata(gcf, "hLegBT", hlegendyBT);
    setappdata(gcf, "hOsyXBT", gca);

endif

# uložení do appdat figúry proměnné KresSmikHarm pro BT gřaf (jestli je legenda)
setappdata(gcf, "KresSmikHarm", KresSmikHarm);


hold off # konec udržení gřafu pro další kreslení do něj .......................


#freqenční wosa by měla být dycky od 0
VobsadDilkyWos (hgrf2, 0, max(f_vektor(1:IndVypis)/1000),"X");
if AmplHarmV == 0
  # jen pro dB, zde maximumo by vždy měla být 0
  # a miminumo vybrat, je tam víc hodnot

  # následující 2 hodnoty se kreslí vždycky, další (snad) miminum nepřesáhnou
  minBlack = min(jednostr_spektrum_black_dB(1:IndVypis));
  minSig = min(jednostr_spektrum_dB(1:IndVypis));
  if KresSmikHarm
    minHarm = min(jednostr_spektrum_F_dB(1:IndVypis));
  else
    minHarm = 9999.9;   #nějaké maximumo které miminumo nemá šanci přelést
  endif

  VobsadDilkyWos(hgrf2, min([minBlack, minSig, minHarm]), 0,"Y");
endif








#ovládání položek menu
try
  #gdyš poprvé nejni men tady ještě obsazené tak následující způsobí botu...
  set (men.editpod1, "enable", 'on');
  set (men.ovlpod2, "enable", 'on');
  set (men.ovlpod3, "enable", 'on');
  set (men.nastPocHarm, "enable", 'on');
  set (men.nastPocPocHarm, "enable", 'on');

  #a z kontext. menu taky
  set (men.kontmenu.pod2, "enable", 'on');
  set (men.kontmenu.pod3, "enable", 'on');
  set (men.kontmenu.nastPocHarm, "enable", 'on');
  set (men.kontmenu.nastPocPocHarm, "enable", 'on');

  # Přiřazení kontextového menu ke FŠEM prfkúm v figúúře, musí tu být znovu,
  # páč to nějak zapomene
  set (findall(gcf), "uicontextmenu", men.kontmenu.hlav);
end



if VolitFile
  #gdyš je překreslení tak si kurzor ovládají oné fuňkce
  set(gcf, 'pointer', 'arrow');  #nečekatiti''''''''''''''''''''''''''''''''''''
endif



endfunction

# konec funkcí *****************************************************************















#*******************************************************************************
# hlavní program----------------------------------------------------------------
#*******************************************************************************



# Tady, rači hned na začátku (i když to tak nevypadá) je definovaná fuňkce,
# která se zavolá při ukončení celé oktávy - je to qůli výmazu filé
# Póówlšelllu, které se používá k indikaci, jeli aktiwní vokno maxima lízováno.
atexit ("Oktavasezavira");






#velikost vobra žofky 0 v pikslích
set (0, 'units','pixels')

#Oktaava takto monitoruje jen PRIMÁRNÍ monitor, no je zadarmo...
[velobr] = get(0,"monitorpositions");
dpi = get(0, 'screenpixelsperinch');  #toto celkem odpovídá a je to fyzické DPI
obrcmvypsir = 2.54* (velobr(3)-velobr(1))/dpi; #skut. rozměr šířky monitoru v cm
obrcmvypvys = 2.54* (velobr(4)-velobr(2))/dpi; #skut. rozměr výšky monitoru v cm








#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#pokus o načtení ini filé s stejným jménem jako toto spuštěné .m filé
#a s rozšířením .NUF (to snad ještě není)


Cestaulozena = '';
AmplHarmV = 0;
Fsmik = 50000;
RadBTfiltru = 2;
JeBTfiltr = true;
PoziceMinula = [-999, -999, -999, -999];


Jminifile = cstrcat(mfilename,'.nuf');

Pocradfile = 0;
radkyfile = [''];

# Otevření souboru pro čtení
fid = fopen(Jminifile, 'r');


# Kontrola, zda se soubor otevřel správně, kdyby néé, tak fid bude = -1
# a kdyš se neotevřel tak nedělat nic
if fid ~= -1    # není rovno

  # Čtení z filé po řádcích
  Pocradfile = 0;
  while ~feof(fid)
    Pocradfile++;
    % Načtení jednoho řádku, takto celý řádek (s :):
    radkyfile {Pocradfile,1} = fgetl(fid);
  end

  # Zavření filé
  fclose(fid);


  # zpracování filé
  Cestaulozena = '';  #dyby ve filé nebylo
  if Pocradfile > 0
    for i = 1 : Pocradfile


      pozice =  strfind(radkyfile {i,1}, Iniplk.amplharmveV);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        AmplHarmV = str2num(radkyfile {i,1}(pozice + 1:end));

        if AmplHarmV ~ 0
          AmplHarmV = 1;  # V
        end
      end


      pozice =  strfind(radkyfile {i,1}, Iniplk.PocKrHarm);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        PocKresHarm = str2num(radkyfile {i,1}(pozice + 1:end));
        if isempty(PocKresHarm)
          PocKresHarm = 200;
        endif
      endif


      pozice =  strfind(radkyfile {i,1}, Iniplk.PocPocHarm);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        PocPocHarm = str2num(radkyfile {i,1}(pozice + 1:end));
        if isempty(PocPocHarm)
          PocPocHarm = 2;
        endif
      endif


      pozice =  strfind(radkyfile {i,1}, Iniplk.zpracdat);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        ZpracDat = str2num(radkyfile {i,1}(pozice + 1:end));
        if isempty(ZpracDat)
          ZpracDat = 1;
        else
          ZpracDat = fix(ZpracDat);
          if ZpracDat < 1 | ZpracDat > 4 # & je and; | je or; ~ je not, cocoti
            ZpracDat = 1;
          endif
        endif
      endif


      pozice =  strfind(radkyfile {i,1}, Iniplk.cestafile);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        Cestaulozena = strtrim (radkyfile {i,1}(pozice + 1:end));
      endif


      pozice =  strfind(radkyfile {i,1}, Iniplk.PoziceFig);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        PoziceMinula = str2num (radkyfile {i,1}(pozice + 1:end));
      endif


      pozice =  strfind(radkyfile {i,1}, Iniplk.pouzBT);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        plk = strtrim (radkyfile {i,1}(pozice + 1:end));
        if strcmp(upper(plk), 'YES')
          JeBTfiltr = true;
        else
          JeBTfiltr = false;
        endif
      endif

      pozice =  strfind(radkyfile {i,1}, Iniplk.fsmikBT);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        Fsmik = str2num (radkyfile {i,1}(pozice + 1:end));
        if isempty(Fsmik)
          Fsmik = 50000;
        else
          Fsmik = fix(Fsmik);
        endif
      endif

      pozice =  strfind(radkyfile {i,1}, Iniplk.radBT);
      if pozice > 0
        pozice = strfind(radkyfile {i,1}, '=');
        RadBTfiltru = str2num (radkyfile {i,1}(pozice + 1:end));
        if isempty(RadBTfiltru)
          RadBTfiltru = 2;
        else
          RadBTfiltru = fix(RadBTfiltru);
          if RadBTfiltru < 1 | RadBTfiltru > 8
            RadBTfiltru = 2;
          endif
        endif
      endif



    endfor

  endif

endif
#xonec čtení filé xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


if exist(Cestaulozena,'dir') == 7    #dyš vrátí 7 tak je to adresář
  Cestafile = Cestaulozena;
endif










# načtení hodnot o všech  monitourech jinak, dyš to oktááva neumí,
# až po přečtení ini filé
# ale funguje to jen we Voknech
[Bota, Monitory] = Zjisti_monitory();


if length(Bota)>0
  #ošetření případné obuvi při zjišťování monitourů PowerodeŠelem

  plk1 = cstrcat('Error occurred while detecting connected monitors using tools outside Octave:'...
              ,newline, Bota ...
              ,newline,newline, 'Correct following values according to reality, because'...
              ,' Octave probably cannot read (or I do not know how to find out) display'...
              ,newline, ' magnification in percent specified in Windows settings,'...
              ,' it is in Settings/System/Display,'...
              ,newline, 'and check resolution of main monitor to see if it is read correctly.'...
              ,newline, ' (If entered values do not correspond to reality, main program'...
              ,' window may not display correctly.)'...
              ,newline, newline, 'Horizontal resolution of main display in pixels:');

  plk2 = cstrcat(newline, newline, 'Vertical resolution of main display in pixels:');

  plk3 = cstrcat(newline, newline, 'Display magnification in percent:');

  plkcel = {plk1, plk2, plk3};
  plktit = 'Manual entry of parameters for size of base window';


  defaults = {velobr(3), velobr(4), 100};
  rowscols = [1,10; 1,10; 1,10];
  vlozeno = inputdlg (plkcel ,plktit ,rowscols , defaults);


  Blbyvstup = false;
  if isempty(vlozeno)
    #vstup byl zrušen
    Blbyvstup = true;
  endif


  # deklarace pole Hlmonitor
  Hlmonitor = struct('sirkaSkut', -999, 'vyskaSkut', -999, 'zvetseni_proc', ...
                      -999, 'sirkaLogic', -999, 'vyskaLogic', -999);


  if Blbyvstup
    # když byl vstup zrušen dáti načtené
    Xrozlmon = velobr(3);
    Yrozlmon = velobr(4);
    ZvetsMon = 100;
  else
    if isnan(str2double(vlozeno{1}))
      Xrozlmon = velobr(3);
    else
      Xrozlmon = str2double(vlozeno{1});
    endif


    if isnan(str2double(vlozeno{2}))
      Yrozlmon = velobr(4);
    else
      Yrozlmon = str2double(vlozeno{2});
    endif


    if isnan(str2double(vlozeno{3}))
      ZvetsMon = 100;
    else
      ZvetsMon = str2double(vlozeno{3});
    endif

  endif

  # no a nastavení pole Hlmonitor podle vstupu:
  Hlmonitor.sirkaLogic = Xrozlmon/ZvetsMon*100;
  Hlmonitor.vyskaLogic = Yrozlmon/ZvetsMon*100;
  Hlmonitor.zvetseni_proc = ZvetsMon;
  Hlmonitor.sirkaSkut = Xrozlmon;
  Hlmonitor.vyskaSkut = Yrozlmon;

  # a taky pole Monitory pro jeden monitor podle vstupu:
  Monitory(1).primarni = 1;
  Monitory(1).sirkaLogic = Hlmonitor.sirkaLogic;
  Monitory(1).vyskaLogic = Hlmonitor.vyskaLogic;
  Monitory(1).zvetseni_proc = Hlmonitor.zvetseni_proc;
  Monitory(1).sirkaSkut = Hlmonitor.sirkaSkut;
  Monitory(1).vyskaSkut = Hlmonitor.vyskaSkut;
  Monitory(1).rucni_vstup = 1;

else
  # dyš není bota tak vybrání hlavního monitoru, aby se nemusel dále hledati

  for i=1 : numel(Monitory)
    if Monitory(i).primarni
      Hlmonitor.sirkaLogic = Monitory(i).sirkaLogic;
      Hlmonitor.vyskaLogic = Monitory(i).vyskaLogic;
      Hlmonitor.zvetseni_proc = Monitory(i).zvetseni_proc;
      Hlmonitor.sirkaSkut = Monitory(i).sirkaSkut;
      Hlmonitor.vyskaSkut = Monitory(i).vyskaSkut;
      break;
    endif
  endfor

#konec ošetření případné obuvi při zjišťování monitourů PowerodeŠelem
endif










[Velpis] = NastavVelPis (Hlmonitor);



hfig1 = figure (1, 'numbertitle', 'off' , 'name', HlavPlk, 'visible', 'off');



# nastavení velikosti figúúry v pikslích podle logické velikosti displayjeje
# a zaokrrouhlit na celá čísla, páč piksle jsou celé
set (hfig1, 'units', 'pixels' , 'position', [  ...
     round(Hlmonitor.sirkaLogic * ZaklVelFig.X), ...
     round(Hlmonitor.vyskaLogic * ZaklVelFig.Y), ...
     round(Hlmonitor.sirkaLogic * ZaklVelFig.Sir), ...
     round(Hlmonitor.vyskaLogic * ZaklVelFig.Vys)]);
PozfigPiksle = get (hfig1, 'position');


#nastavení normalizace qůli zjištění normalizačních jednotek
set (hfig1, 'units', 'normalized');
Pozfig = get (hfig1, 'position');


# Uložení základní normalízované pozice figuury po spuštění do appdat figúry
# (tady aby byla normálízed)
setappdata(hfig1,'ZaklPosFig',Pozfig);


#a dál je to zase v PIKSLÍCH:
set (hfig1, 'units','pixels','papertype','a4','paperorientation','landscape');
set (hfig1, 'paperunits','centimeters');
#menubar none zruší jejich menu, bude jen moje:
set (hfig1, 'resize','on','menubar','none');

set (hfig1, 'visible', 'on');





# nastavení min a max rozměrů figúry tady V PIKSLÍCH a zaokr. na celá čísla:
# nasobSirky je úprava podle mého zkoušení aby se plky v min. okně nepřekrývaly
nasobSirky =  2.2189E-08 * Hlmonitor.sirkaLogic^2 - 1.7899E-04 ...
              * Hlmonitor.sirkaLogic + 1.0591E+00;
minSir = round(PozfigPiksle(3)*nasobSirky);
maxSir = round(PozfigPiksle(3));
minVys = round(PozfigPiksle(4)*0.82);
maxVys = round(PozfigPiksle(4));

% a jejich uložení do ÚserData od figúry
set (hfig1, 'UserData', struct('zacX',PozfigPiksle(1),'minSir',minSir, ...
     'maxSir',maxSir,'zacY',PozfigPiksle(2),'minVys',minVys,'maxVys',maxVys));




# Z relativních pozic legend vzhledem k x ose (v rel. jednotkách [0 až 1]) se
# tu od 11.2.2026 používá jen pozice (2) - výškové umístění, protože se mě
# asi nepodařilo najít jedlou relativní pozici pro umístění vodorovné a to
# pak nesedělo jedle, takže jsem vodorovnou pozici nechal na octááve
# bližší k tomu je ve fuňkci nastavPozLegendyRelatkOse(). Hodnoty jsou tu
# ty, se kterými to jaksi nejlíp pasovalo pro anglickou verzi.
#
# Relativní pozice legendy v rámci osy pro gřaf hlav. průběhu
rel_pos_leg = [0.82, -0.23, 0.19, 0.15];
setappdata(hfig1,'RelPosLegHL',rel_pos_leg);  #a její uložení do appdat figúry

# Relativní pozice legendy v rámci osy pro gřaf harmonických (je menší)
rel_pos_leg_BT = [0.66, -0.225, 0.4, 0.15];
setappdata(hfig1,'RelPosLegBT',rel_pos_leg_BT); #a její uložení do appdat figúry





# a nastavení pozice figúry jaká byla při minulém ukončení programu, jeli
if  all(PoziceMinula > 0)
  if PoziceMinula(3) <= PozfigPiksle(3) && PoziceMinula(4) <= PozfigPiksle(4)
    # Minulou pozici nastavit jen dyš program minule neskončil s maximalízovaným
    # woknem, páč příkaz k maksima lízaci wokna woktáwe nemá, a uložené rozměry
    # jsou pro okno maximalízované, a kdyš by se tu nastavily, bude wokno větší
    # a nepújde se dostat na horní lištu (nebude viděti)
    #
    # Ale taky kontrolovat počátek Y a výšku figúúry, páč nevím číím, ale i tak
    # se vobčas zobrazí s horní lištou nahoře mimo vobražofku, což je blbé



    if PoziceMinula(4) + PoziceMinula(2) > maxVys

      if PoziceMinula(4) > maxVys
        PoziceMinula(4) = maxVys;
      endif
      if PoziceMinula(4) + PoziceMinula(2) > PozfigPiksle(4) + PozfigPiksle(2)
        PoziceMinula(2) = PozfigPiksle(2);
      endif

    endif

    set (hfig1, 'position', PoziceMinula);

  endif
endif






# groot je default graphics systém
# třeba:  get(groot, 'ScreenSize')
#
# gcf   je current figúre
# gca   je currenx axes
# gco   je current objekt

# třeba nastavení defaultního písma:
# set(groot, 'DefaultTextFontName', 'Times New Roman')
# set(groot, 'DefaultTextFontName', 'Arial')
# set(groot, 'DefaultTextFontSize', Velpis)






Jemriz = true;  #po spuštění mřížky jsou, tak takto


# první zavolání ocaď
# při prvním volání ignorovat zatím neobsazene a nefinované vst. proměnné pomocí
# prázdného argumentu []
[Cestafile, Jmfile, pocfile, hgrf1, hgrf2] = VypDFT (Cestafile, [], [], [], ...
                                       [], Velpis, [], true, false, false);






#*******************************************************************************
#menu, až nakonec, aby už byly figuury a jejich handleové ----------------------

#hl menu - !! v hl menu akcelerátory nějak nefungujou !!!
men.zaklovl = uimenu ("text", "DFT control");
men.hlnast = uimenu ("text", "Settings");
men.zakledit = uimenu ("text", "Editing charts");







#podmenu
plk = cstrcat(plknastpod{1});
men.nastpod(1) = uimenu (men.hlnast, "text", plk, "menuselectedfcn", ...
           "PrejezZprac (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, 1)");

plk = cstrcat(plknastpod{2});
men.nastpod(2) = uimenu (men.hlnast, "text", plk, "menuselectedfcn", ...
           "PrejezZprac (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, 2)");

plk = cstrcat(plknastpod{3});
men.nastpod(3) = uimenu (men.hlnast, "text", plk, "menuselectedfcn", ...
           "PrejezZprac (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, 3)");

plk = cstrcat(plknastpod{4});
men.nastpod(4) = uimenu (men.hlnast, "text", plk, "menuselectedfcn", ...
           "PrejezZprac (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, 4)");





plk = cstrcat("Choice of using Butterworth LP filter calculation and its parameters");
men.nastDPButt = uimenu (men.hlnast, "text", plk, "separator", "on", ...
           "menuselectedfcn", "NastavButt (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");





plk = cstrcat("Switch [dB - V] for drawing Y-axis of graph of harmonics: now it is ");
if AmplHarmV == 0
  plk = cstrcat(plk, 'in [dB]');
else
  plk = cstrcat(plk, 'in [V]');
end
men.nastpodharm = uimenu (men.hlnast, "text", plk, "separator", "on", ...
          "menuselectedfcn", "ZmenKreslHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");



plk = cstrcat("Change in number of plotted harmonics ");
plk = cstrcat(plk, '(now it is ',num2str(PocKresHarm, "%d"), ' i.e. up to ');
plk = cstrcat(plk, num2str(sigfig(Fvypis/1000,4)),' kHz)');
men.nastPocHarm = uimenu (men.hlnast, "text", plk, ...
           "menuselectedfcn", "ZmenPocKreslHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");


plk = cstrcat("Change in last calculated harmonics ");
plk = cstrcat(plk, '(now it is ',num2str(PocPocHarm + 1, "%d"), '. i.e. up to ');
plk = cstrcat(plk, num2str(sigfig(FpocTHD/1000,4)),' kHz)');
men.nastPocPocHarm = uimenu (men.hlnast, "text", plk, ...
           "menuselectedfcn", "ZmenPocPocitHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");






men.ovlpod1 = uimenu (men.zaklovl, "label", "Load input file", ...
           "accelerator", "b", "menuselectedfcn",...
           "[Cestafile, Jmfile, pocfile, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, pocfile, true, false, false)");

#vono to de i bez parenta, třeba viz men.nastpod1
men.ovlpod2 = uimenu ("parent", men.zaklovl, "label", "Save as image with &lower resolution", ...
           "accelerator", "l", "separator", "on" , "menuselectedfcn", ...
           "[hgrf1, hgrf2] = UlozdofileMensi (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");

men.ovlpod3 = uimenu ("parent", men.zaklovl, "label", "Save as image with &higher resolution", ...
           "accelerator", "h", "menuselectedfcn",  "[hgrf1, hgrf2] = UlozdofileVetsi (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");

men.ovlpod4 = uimenu ("parent", men.zaklovl, "label", "&Close this window", ...
           "accelerator", "c","separator", "on" , "menuselectedfcn", "close (hfig1)");



men.editpod1 = uimenu (men.zakledit, "text", "&Grids in graphs", "accelerator", "g", ...
           "menuselectedfcn", "[Jemriz] = FunNufmriz (Jemriz, hgrf1, hgrf2)");








# a kontekstové menu

# Vytvoření kontextového menu
men.kontmenu.hlav = uicontextmenu(hfig1);

# Přidání položek do kontextového menu
men.kontmenu.pod1 = uimenu(men.kontmenu.hlav, 'Label', 'Load input file', ...
          "menuselectedfcn", ...
          "[Cestafile, Jmfile, pocfile, hgrf1, hgrf2] = VypDFT (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis, pocfile, true, false, false)");

men.kontmenu.pod2 = uimenu(men.kontmenu.hlav, 'Label', 'Save as image with &lower resolution', ...
          "separator", "on" , "menuselectedfcn", ...
          "[hgrf1, hgrf2] = UlozdofileMensi (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");

men.kontmenu.pod3 = uimenu(men.kontmenu.hlav, 'Label', 'Save as image with &higher resolution', ...
          "menuselectedfcn", ...
          "[hgrf1, hgrf2] = UlozdofileVetsi (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");



plk = cstrcat("Choice of using Butterworth LP filter calculation and its parameters");
men.kontmenu.nastDPButt = uimenu (men.kontmenu.hlav, "text", plk, "separator", "on", ...
           "menuselectedfcn", "NastavButt (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");



plk = cstrcat("Switch [dB - V] for drawing Y-axis of graph of harmonics: now it is ");
if AmplHarmV == 0
  plk = cstrcat(plk, 'in [dB]');
else
  plk = cstrcat(plk, 'in [V]');
end
men.kontmenu.nastharm = uimenu (men.kontmenu.hlav, "text", plk, "separator", "on", ...
          "menuselectedfcn", "ZmenKreslHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");



plk = cstrcat("Change in number of plotted harmonics ");
plk = cstrcat(plk, '(now it is ',num2str(PocKresHarm, "%d"), ' i.e. up to ');
plk = cstrcat(plk, num2str(sigfig(Fvypis/1000,4)),' kHz)');
men.kontmenu.nastPocHarm = uimenu (men.kontmenu.hlav, "text", plk, ...
           "menuselectedfcn", "ZmenPocKreslHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");

plk = cstrcat("Change in last calculated harmonics ");
plk = cstrcat(plk, '(now it is ',num2str(PocPocHarm + 1, "%d"), '. i.e. up to ');
plk = cstrcat(plk, num2str(sigfig(FpocTHD/1000,4)),' kHz)');
men.kontmenu.nastPocPocHarm = uimenu (men.kontmenu.hlav, "text", plk, ...
           "menuselectedfcn", "ZmenPocPocitHarm (Cestafile, Jmfile, hgrf1, hgrf2, men, Velpis)");



men.kontmenu.ZavrWokno = uimenu("parent", men.kontmenu.hlav, 'Label', '&Close this window', ...
          "separator", "on" , "menuselectedfcn", "close (hfig1)");


# Přiřazení kontextového menu k figúúře a ke FŠEM jejím onýšům
set (findall(hfig1), "uicontextmenu", men.kontmenu.hlav);











#přednastavení menu pro zpracování dat z filé
set(men.nastpod(ZpracDat), "checked", "on")
if ~ VsechnyVybery     #to je (if not VsechnyVybery)
  #znepřístupnění ostatních výběrů, kromě celého filé
  #tady taky, páč kdyš se obsazuje VsechnyVybery tak menu "men" ještě neexistuje
  set (men.nastpod(1), "text", cstrcat('NOT POSSIBLE - ', plknastpod{1}));
  set (men.nastpod(2), "text", cstrcat('NOT POSSIBLE - ', plknastpod{2}));
  set (men.nastpod(3), "text", cstrcat('NOT POSSIBLE - ', plknastpod{3}));

  set (men.nastpod(1), "enable", 'off');
  set (men.nastpod(2), "enable", 'off');
  set (men.nastpod(3), "enable", 'off');

endif




# následující poslouchač pomocí addlistener (od Duck.ia) nějak nefunguje
# addlistener(hFig, 'CloseRequestFcn', @(src, event) closeFigure(src));

# Přidání poslouchače události zavření figure s hfig1, qůli uložení nastavení
# do filé k předávání proměnných viz plk ve fuňkci !!!!!!!
set(hfig1, 'CloseRequestFcn', @(src, event) Figurasezavira(src));





# Aktívace omezení rozměrů figůry MUSÍ být až tady (dál od nastavení pozice
# figúry podle minula), páč dyš je těsně za nastavením oné pozice tak
# se program s takto nastavenou figúrou spustí, ALE při první změně
# rozměrů ZDECHNE celá Oktáva !!!!!!!!!!!! a čert ví proč...
aktivuj_omez_rozm(hfig1)








if (pocfile < 1);  # znepřístupnění menu pro hotový výstup
                   #(třeba editace mříšky) dyš poprvé nejni filé

  set (men.editpod1, "enable", 'off');
  set (men.ovlpod2, "enable", 'off');
  set (men.ovlpod3, "enable", 'off');
  set (men.nastPocHarm, "enable", 'off');
  set (men.nastPocPocHarm, "enable", 'off');

  #a z kontext. menu taky
  set (men.kontmenu.pod2, "enable", 'off');
  set (men.kontmenu.pod3, "enable", 'off');
  set (men.kontmenu.nastPocHarm, "enable", 'off');
  set (men.kontmenu.nastPocPocHarm, "enable", 'off');

endif



#konec menu-------------------------------------------------------------------




















