sarkit-convert 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sarkit_convert/iceye.py CHANGED
@@ -10,12 +10,12 @@ Note: In the development of this converter "Iceye Product Metadata" description
10
10
  """
11
11
 
12
12
  import argparse
13
- import copy
13
+ import datetime
14
14
  import pathlib
15
15
 
16
16
  import dateutil.parser
17
17
  import h5py
18
- import lxml.builder
18
+ import lxml.etree
19
19
  import numpy as np
20
20
  import numpy.linalg as npl
21
21
  import numpy.polynomial.polynomial as npp
@@ -24,6 +24,7 @@ import sarkit.wgs84
24
24
  from sarkit import _constants
25
25
  from sarkit.verification import SicdConsistency
26
26
 
27
+ from sarkit_convert import __version__
27
28
  from sarkit_convert import _utils as utils
28
29
 
29
30
  NSMAP = {
@@ -108,88 +109,54 @@ def compute_apc_poly(h5_attrs, start_time, stop_time):
108
109
  return apc_poly
109
110
 
110
111
 
111
- def _update_radiometric_node(sicd_xmltree):
112
+ def _update_radiometric_node(sicd_ew):
112
113
  """Use existing metadata to populate the Radiometric XML node."""
113
- xmlhelp = sksicd.XmlHelper(copy.deepcopy(sicd_xmltree))
114
114
 
115
- def get_slant_plane_area(xmlhelp):
116
- row_imp_resp_bw = xmlhelp.load("./{*}Grid/{*}Row/{*}ImpRespBW")
117
- col_imp_resp_bw = xmlhelp.load("./{*}Grid/{*}Col/{*}ImpRespBW")
115
+ def get_slant_plane_area(sicd_ew):
116
+ row_imp_resp_bw = sicd_ew["Grid"]["Row"]["ImpRespBW"]
117
+ col_imp_resp_bw = sicd_ew["Grid"]["Col"]["ImpRespBW"]
118
118
  range_weight_f = azimuth_weight_f = 1.0
119
- row_wgt_funct = xmlhelp.load("./{*}Grid/{*}Row/{*}WgtFunct")
120
- if row_wgt_funct is not None:
119
+ row_wgt_funct = sicd_ew["Grid"]["Row"]["WgtFunct"]
120
+ if len(row_wgt_funct) > 0:
121
121
  var = np.var(row_wgt_funct)
122
122
  mean = np.mean(row_wgt_funct)
123
123
  range_weight_f += var / (mean * mean)
124
- col_wgt_funct = xmlhelp.load("./{*}Grid/{*}Col/{*}WgtFunct")
125
- if col_wgt_funct is not None:
124
+ col_wgt_funct = sicd_ew["Grid"]["Col"]["WgtFunct"]
125
+ if len(col_wgt_funct) > 0:
126
126
  var = np.var(col_wgt_funct)
127
127
  mean = np.mean(col_wgt_funct)
128
128
  azimuth_weight_f += var / (mean * mean)
129
129
  return (range_weight_f * azimuth_weight_f) / (row_imp_resp_bw * col_imp_resp_bw)
130
130
 
131
- sp_area = get_slant_plane_area(xmlhelp)
132
- radiometric_node = xmlhelp.element_tree.find("./{*}Radiometric")
133
- scpcoa_slope_ang = xmlhelp.load("./{*}SCPCOA/{*}SlopeAng")
134
- scpcoa_graze_ang = xmlhelp.load("./{*}SCPCOA/{*}GrazeAng")
135
- if radiometric_node.find("{*}BetaZeroSFPoly") is None:
136
- if radiometric_node.find("{*}RCSSFPoly") is not None:
137
- beta_zero_sf_poly_coefs = (
138
- xmlhelp.load_elem(radiometric_node.find("{*}RCSSFPoly")) / sp_area
131
+ sp_area = get_slant_plane_area(sicd_ew)
132
+ radiometric = sicd_ew["Radiometric"]
133
+ scpcoa_slope_ang = sicd_ew["SCPCOA"]["SlopeAng"]
134
+ scpcoa_graze_ang = sicd_ew["SCPCOA"]["GrazeAng"]
135
+ beta_zero_sf_poly_coefs = None
136
+ if "BetaZeroSFPoly" in radiometric:
137
+ beta_zero_sf_poly_coefs = radiometric["BetaZeroSFPoly"]
138
+ else:
139
+ if "RCSSFPoly" in radiometric:
140
+ beta_zero_sf_poly_coefs = radiometric["RCSSFPoly"] / sp_area
141
+ elif "SigmaZeroSFPoly" in radiometric:
142
+ beta_zero_sf_poly_coefs = radiometric["SigmaZeroSFPoly"] / np.cos(
143
+ np.deg2rad(scpcoa_slope_ang)
139
144
  )
140
- elif radiometric_node.find("{*}SigmaZeroSFPoly") is not None:
141
- beta_zero_sf_poly_coefs = xmlhelp.load_elem(
142
- radiometric_node.find("{*}SigmaZeroSFPoly")
143
- ) / np.cos(np.deg2rad(scpcoa_slope_ang))
144
- elif radiometric_node.find("{*}GammaZeroSFPoly") is not None:
145
- beta_zero_sf_poly_coefs = xmlhelp.load_elem(
146
- radiometric_node.find("{*}GammaZeroSFPoly")
147
- ) * (
145
+ elif "GammaZeroSFPoly" in radiometric:
146
+ beta_zero_sf_poly_coefs = radiometric["GammaZeroSFPoly"] * (
148
147
  np.sin(np.deg2rad(scpcoa_graze_ang))
149
148
  / np.cos(np.deg2rad(scpcoa_slope_ang))
150
149
  )
151
- else:
152
- beta_zero_sf_poly_coefs = xmlhelp.load_elem(
153
- radiometric_node.find("{*}BetaZeroSFPoly")
154
- )
155
150
 
156
151
  if beta_zero_sf_poly_coefs is not None:
157
- # In other words, none of the SF polynomials are populated.
158
- if radiometric_node.find("{*}RCSSFPoly") is None:
159
- rcs_sf_poly_coefs = beta_zero_sf_poly_coefs * sp_area
160
- if radiometric_node.find("{*}SigmaZeroSFPoly") is None:
161
- sigma_zero_sf_poly_coefs = beta_zero_sf_poly_coefs * np.cos(
162
- np.deg2rad(scpcoa_slope_ang)
163
- )
164
- if radiometric_node.find("{*}GammaZeroSFPoly") is None:
165
- gamma_zero_sf_poly_coefs = beta_zero_sf_poly_coefs * (
166
- np.cos(np.deg2rad(scpcoa_slope_ang))
167
- / np.sin(np.deg2rad(scpcoa_graze_ang))
168
- )
169
-
170
- sicd = lxml.builder.ElementMaker(
171
- namespace=NSMAP["sicd"], nsmap={None: NSMAP["sicd"]}
172
- )
173
- new_radiometric_node = sicd.Radiometric(
174
- sicd.RCSSFPoly(),
175
- sicd.SigmaZeroSFPoly(),
176
- sicd.BetaZeroSFPoly(),
177
- sicd.GammaZeroSFPoly(),
178
- )
179
- sksicd.Poly2dType().set_elem(
180
- new_radiometric_node.find("./{*}RCSSFPoly"), rcs_sf_poly_coefs
181
- )
182
- sksicd.Poly2dType().set_elem(
183
- new_radiometric_node.find("./{*}SigmaZeroSFPoly"), sigma_zero_sf_poly_coefs
184
- )
185
- sksicd.Poly2dType().set_elem(
186
- new_radiometric_node.find("./{*}BetaZeroSFPoly"), beta_zero_sf_poly_coefs
187
- )
188
- sksicd.Poly2dType().set_elem(
189
- new_radiometric_node.find("./{*}GammaZeroSFPoly"), gamma_zero_sf_poly_coefs
190
- )
191
-
192
- return new_radiometric_node
152
+ radiometric["RCSSFPoly"] = beta_zero_sf_poly_coefs * sp_area
153
+ radiometric["SigmaZeroSFPoly"] = beta_zero_sf_poly_coefs * np.cos(
154
+ np.deg2rad(scpcoa_slope_ang)
155
+ )
156
+ radiometric["BetaZeroSFPoly"] = beta_zero_sf_poly_coefs
157
+ radiometric["GammaZeroSFPoly"] = beta_zero_sf_poly_coefs * (
158
+ np.cos(np.deg2rad(scpcoa_slope_ang)) / np.sin(np.deg2rad(scpcoa_graze_ang))
159
+ )
193
160
 
194
161
 
195
162
  def _get_x_y_coords(num_row_col, spacing_row_col, scp_pixel, start_row_col):
@@ -226,7 +193,7 @@ def _calc_deltaks(x_coords, y_coords, deltak_coa_poly, imp_resp_bw, spacing):
226
193
  return min_deltak, max_deltak
227
194
 
228
195
 
229
- def hdf5_to_sicd(h5_filename, sicd_filename, classification, ostaid="Unknown"):
196
+ def hdf5_to_sicd(h5_filename, sicd_filename, classification, ostaid):
230
197
  """Converts Iceye native SLC h5 files to NGA standard SICD files.
231
198
 
232
199
  Parameters
@@ -237,7 +204,7 @@ def hdf5_to_sicd(h5_filename, sicd_filename, classification, ostaid="Unknown"):
237
204
  path of the output SICD file.
238
205
  classification: str
239
206
  content of the /SICD/CollectionInfo/Classification node in the SICD XML.
240
- ostaid: str, optional
207
+ ostaid: str
241
208
  content of the originating station ID (OSTAID) field of the NITF header.
242
209
 
243
210
  """
@@ -411,25 +378,27 @@ def hdf5_to_sicd(h5_filename, sicd_filename, classification, ostaid="Unknown"):
411
378
  / 2,
412
379
  )
413
380
 
414
- x_order = min(3, range_scp_m.shape[0] - 1)
415
- y_order = min(3, range_scp_m.shape[1] - 1)
381
+ x_order = min(4, range_scp_m.shape[0] - 1)
382
+ y_order = min(4, range_scp_m.shape[1] - 1)
416
383
 
417
384
  # fit the doppler centroid sample array
418
- dop_centroid_poly_coefs = utils.polyfit2d(
385
+ dop_centroid_poly_coefs = utils.polyfit2d_tol(
419
386
  range_scp_m.flatten(),
420
387
  azimuth_scp_m.flatten(),
421
388
  dc_sample_array.flatten(),
422
389
  x_order,
423
390
  y_order,
391
+ 1e-2,
424
392
  )
425
393
  doppler_rate_sampled = npp.polyval(azimuth_scp_m, drca_poly_coefs)
426
394
  time_coa = dc_zd_times + dc_sample_array / doppler_rate_sampled
427
- time_coa_poly_coefs = utils.polyfit2d(
395
+ time_coa_poly_coefs = utils.polyfit2d_tol(
428
396
  range_scp_m.flatten(),
429
397
  azimuth_scp_m.flatten(),
430
398
  time_coa.flatten(),
431
399
  x_order,
432
400
  y_order,
401
+ 1e-3,
433
402
  )
434
403
 
435
404
  return dop_centroid_poly_coefs, time_coa_poly_coefs
@@ -482,7 +451,6 @@ def hdf5_to_sicd(h5_filename, sicd_filename, classification, ostaid="Unknown"):
482
451
  row_kctr = str(center_frequency / (_constants.speed_of_light / 2))
483
452
  row_deltak_coa_poly = np.array([[0]])
484
453
 
485
- col_ss = col_ss
486
454
  col_imp_res_bw = col_bw
487
455
  col_sgn = -1
488
456
  col_kctr = 0
@@ -553,230 +521,180 @@ def hdf5_to_sicd(h5_filename, sicd_filename, classification, ostaid="Unknown"):
553
521
  ]
554
522
 
555
523
  # Build XML
556
- sicd = lxml.builder.ElementMaker(
557
- namespace=NSMAP["sicd"], nsmap={None: NSMAP["sicd"]}
558
- )
559
- collection_info = sicd.CollectionInfo(
560
- sicd.CollectorName(collector_name),
561
- sicd.CoreName(core_name),
562
- sicd.CollectType(collect_type),
563
- sicd.RadarMode(sicd.ModeType(mode_type), sicd.ModeID(mode_id)),
564
- sicd.Classification(classification),
565
- )
566
- image_creation = sicd.ImageCreation(
567
- sicd.Application(creation_application),
568
- sicd.DateTime(creation_date_time.isoformat() + "Z"),
569
- sicd.Site(ostaid),
570
- )
571
- image_data = sicd.ImageData(
572
- sicd.PixelType(pixel_type),
573
- sicd.NumRows(str(num_rows)),
574
- sicd.NumCols(str(num_cols)),
575
- sicd.FirstRow(str(first_row)),
576
- sicd.FirstCol(str(first_col)),
577
- sicd.FullImage(sicd.NumRows(str(num_rows)), sicd.NumCols(str(num_cols))),
578
- sicd.SCPPixel(sicd.Row(str(scp_pixel[0])), sicd.Col(str(scp_pixel[1]))),
579
- )
580
-
581
- def make_xyz(arr):
582
- return [sicd.X(str(arr[0])), sicd.Y(str(arr[1])), sicd.Z(str(arr[2]))]
583
-
584
- def make_llh(arr):
585
- return [sicd.Lat(str(arr[0])), sicd.Lon(str(arr[1])), sicd.HAE(str(arr[2]))]
586
-
587
- def make_ll(arr):
588
- return [sicd.Lat(str(arr[0])), sicd.Lon(str(arr[1]))]
589
-
590
- # Add GeoData with placeholder corners
591
- geo_data = sicd.GeoData(
592
- sicd.EarthModel("WGS_84"),
593
- sicd.SCP(sicd.ECF(*make_xyz(scp_ecf)), sicd.LLH(*make_llh(scp_llh))),
594
- sicd.ImageCorners(
595
- sicd.ICP({"index": "1:FRFC"}, *make_ll([0, 0])),
596
- sicd.ICP({"index": "2:FRLC"}, *make_ll([0, 0])),
597
- sicd.ICP({"index": "3:LRLC"}, *make_ll([0, 0])),
598
- sicd.ICP({"index": "4:LRFC"}, *make_ll([0, 0])),
599
- ),
600
- )
601
-
602
- grid = sicd.Grid(
603
- sicd.ImagePlane(image_plane),
604
- sicd.Type(grid_type),
605
- sicd.TimeCOAPoly(),
606
- sicd.Row(
607
- sicd.UVectECF(*make_xyz(row_uvect_ecf)),
608
- sicd.SS(str(row_ss)),
609
- sicd.ImpRespWid(str(row_imp_res_wid)),
610
- sicd.Sgn(str(row_sgn)),
611
- sicd.ImpRespBW(str(row_imp_res_bw)),
612
- sicd.KCtr(str(row_kctr)),
613
- sicd.DeltaK1(str(row_delta_k1)),
614
- sicd.DeltaK2(str(row_delta_k2)),
615
- sicd.DeltaKCOAPoly(),
616
- sicd.WgtType(
617
- sicd.WindowName(
618
- str(row_win),
619
- )
620
- ),
621
- ),
622
- sicd.Col(
623
- sicd.UVectECF(*make_xyz(col_uvect_ecf)),
624
- sicd.SS(str(col_ss)),
625
- sicd.ImpRespWid(str(col_imp_res_wid)),
626
- sicd.Sgn(str(col_sgn)),
627
- sicd.ImpRespBW(str(col_imp_res_bw)),
628
- sicd.KCtr(str(col_kctr)),
629
- sicd.DeltaK1(str(col_delta_k1)),
630
- sicd.DeltaK2(str(col_delta_k2)),
631
- sicd.DeltaKCOAPoly(),
632
- sicd.WgtType(
633
- sicd.WindowName(
634
- str(col_win),
635
- )
636
- ),
637
- ),
638
- )
639
- sksicd.Poly2dType().set_elem(grid.find("./{*}TimeCOAPoly"), time_coa_poly)
640
- sksicd.Poly2dType().set_elem(
641
- grid.find("./{*}Row/{*}DeltaKCOAPoly"), row_deltak_coa_poly
642
- )
643
- sksicd.Poly2dType().set_elem(
644
- grid.find("./{*}Col/{*}DeltaKCOAPoly"), col_deltak_coa_poly
645
- )
646
-
647
- timeline = sicd.Timeline(
648
- sicd.CollectStart(collect_start.isoformat() + "Z"),
649
- sicd.CollectDuration(str(collect_duration)),
650
- sicd.IPP(
651
- {"size": "1"},
652
- sicd.Set(
653
- {"index": "1"},
654
- sicd.TStart(str(t_start)),
655
- sicd.TEnd(str(t_end)),
656
- sicd.IPPStart(str(ipp_start)),
657
- sicd.IPPEnd(str(ipp_end)),
658
- sicd.IPPPoly(),
659
- ),
660
- ),
661
- )
662
- sksicd.PolyType().set_elem(timeline.find("./{*}IPP/{*}Set/{*}IPPPoly"), ipp_poly)
663
-
664
- position = sicd.Position(sicd.ARPPoly())
665
- sksicd.XyzPolyType().set_elem(position.find("./{*}ARPPoly"), apc_poly)
666
-
667
- radar_collection = sicd.RadarCollection(
668
- sicd.TxFrequency(sicd.Min(str(tx_freq_min)), sicd.Max(str(tx_freq_max))),
669
- sicd.Waveform(
670
- {"size": "1"},
671
- sicd.WFParameters(
672
- {"index": "1"},
673
- sicd.TxPulseLength(str(tx_pulse_length)),
674
- sicd.TxRFBandwidth(str(tx_rf_bw)),
675
- sicd.TxFreqStart(str(tx_freq_min)),
676
- sicd.TxFMRate(str(tx_fm_rate)),
677
- sicd.RcvDemodType(rcv_demod_type),
678
- sicd.ADCSampleRate(str(adc_sample_rate)),
679
- sicd.RcvFMRate(str(0)),
680
- ),
681
- ),
682
- sicd.TxPolarization(tx_polarization),
683
- sicd.RcvChannels(
684
- {"size": "1"},
685
- sicd.ChanParameters(
686
- {"index": "1"},
687
- sicd.TxRcvPolarization(tx_rcv_polarization),
688
- ),
689
- ),
690
- )
691
-
692
- image_formation = sicd.ImageFormation(
693
- sicd.RcvChanProc(sicd.NumChanProc("1"), sicd.ChanIndex("1")),
694
- sicd.TxRcvPolarizationProc(tx_rcv_polarization_proc),
695
- sicd.TStartProc(str(t_start_proc)),
696
- sicd.TEndProc(str(t_end_proc)),
697
- sicd.TxFrequencyProc(
698
- sicd.MinProc(str(tx_freq_proc[0])), sicd.MaxProc(str(tx_freq_proc[1]))
699
- ),
700
- sicd.ImageFormAlgo(image_form_algo),
701
- sicd.STBeamComp(st_beam_comp),
702
- sicd.ImageBeamComp(image_beam_comp),
703
- sicd.AzAutofocus(az_autofocus),
704
- sicd.RgAutofocus(rg_autofocus),
705
- )
706
-
707
- radiometric = sicd.Radiometric(
708
- sicd.BetaZeroSFPoly(),
709
- )
710
- sksicd.Poly2dType().set_elem(
711
- radiometric.find("./{*}BetaZeroSFPoly"), beta_zero_sf_poly
712
- )
713
-
714
- rma = sicd.RMA(
715
- sicd.RMAlgoType(rma_algo_type),
716
- sicd.ImageType(image_type),
717
- sicd.INCA(
718
- sicd.TimeCAPoly(),
719
- sicd.R_CA_SCP(str(r_ca_scp)),
720
- sicd.FreqZero(str(freq_zero)),
721
- sicd.DRateSFPoly(),
722
- sicd.DopCentroidPoly(),
723
- sicd.DopCentroidCOA(dop_centroid_coa),
724
- ),
725
- )
726
- sksicd.PolyType().set_elem(rma.find("./{*}INCA/{*}TimeCAPoly"), time_ca_poly)
727
- sksicd.Poly2dType().set_elem(rma.find("./{*}INCA/{*}DRateSFPoly"), dr_sf_poly)
728
- sksicd.Poly2dType().set_elem(
729
- rma.find("./{*}INCA/{*}DopCentroidPoly"), dop_centroid_poly
730
- )
524
+ sicd_xml_obj = lxml.etree.Element(
525
+ f"{{{NSMAP['sicd']}}}SICD", nsmap={None: NSMAP["sicd"]}
526
+ )
527
+ sicd_ew = sksicd.ElementWrapper(sicd_xml_obj)
528
+ sicd_ew["CollectionInfo"] = {
529
+ "CollectorName": collector_name,
530
+ "CoreName": core_name,
531
+ "CollectType": collect_type,
532
+ "RadarMode": {
533
+ "ModeType": mode_type,
534
+ "ModeID": mode_id,
535
+ },
536
+ "Classification": classification,
537
+ }
538
+ sicd_ew["ImageCreation"] = {
539
+ "Application": creation_application,
540
+ "DateTime": creation_date_time,
541
+ }
542
+ sicd_ew["ImageData"] = {
543
+ "PixelType": pixel_type,
544
+ "NumRows": num_rows,
545
+ "NumCols": num_cols,
546
+ "FirstRow": first_row,
547
+ "FirstCol": first_col,
548
+ "FullImage": {
549
+ "NumRows": num_rows,
550
+ "NumCols": num_cols,
551
+ },
552
+ "SCPPixel": scp_pixel,
553
+ }
554
+
555
+ sicd_ew["GeoData"] = {
556
+ "EarthModel": "WGS_84",
557
+ "SCP": {
558
+ "ECF": scp_ecf,
559
+ "LLH": scp_llh,
560
+ },
561
+ }
562
+
563
+ sicd_ew["Grid"] = {
564
+ "ImagePlane": image_plane,
565
+ "Type": grid_type,
566
+ "TimeCOAPoly": time_coa_poly,
567
+ "Row": {
568
+ "UVectECF": row_uvect_ecf,
569
+ "SS": row_ss,
570
+ "ImpRespWid": row_imp_res_wid,
571
+ "Sgn": row_sgn,
572
+ "ImpRespBW": row_imp_res_bw,
573
+ "KCtr": row_kctr,
574
+ "DeltaK1": row_delta_k1,
575
+ "DeltaK2": row_delta_k2,
576
+ "DeltaKCOAPoly": row_deltak_coa_poly,
577
+ "WgtType": {
578
+ "WindowName": row_win,
579
+ },
580
+ },
581
+ "Col": {
582
+ "UVectECF": col_uvect_ecf,
583
+ "SS": col_ss,
584
+ "ImpRespWid": col_imp_res_wid,
585
+ "Sgn": col_sgn,
586
+ "ImpRespBW": col_imp_res_bw,
587
+ "KCtr": col_kctr,
588
+ "DeltaK1": col_delta_k1,
589
+ "DeltaK2": col_delta_k2,
590
+ "DeltaKCOAPoly": col_deltak_coa_poly,
591
+ "WgtType": {
592
+ "WindowName": col_win,
593
+ },
594
+ },
595
+ }
596
+
597
+ sicd_ew["Timeline"] = {
598
+ "CollectStart": collect_start,
599
+ "CollectDuration": collect_duration,
600
+ "IPP": {
601
+ "@size": 1,
602
+ "Set": [
603
+ {
604
+ "@index": 1,
605
+ "TStart": t_start,
606
+ "TEnd": t_end,
607
+ "IPPStart": ipp_start,
608
+ "IPPEnd": ipp_end,
609
+ "IPPPoly": ipp_poly,
610
+ }
611
+ ],
612
+ },
613
+ }
731
614
 
732
- sicd_xml_obj = sicd.SICD(
733
- collection_info,
734
- image_creation,
735
- image_data,
736
- geo_data,
737
- grid,
738
- timeline,
739
- position,
740
- radar_collection,
741
- image_formation,
742
- rma,
743
- )
615
+ sicd_ew["Position"]["ARPPoly"] = apc_poly
744
616
 
745
- scp_coa = sksicd.compute_scp_coa(sicd_xml_obj.getroottree())
746
- sicd_xml_obj = sicd.SICD(
747
- collection_info,
748
- image_creation,
749
- image_data,
750
- geo_data,
751
- grid,
752
- timeline,
753
- position,
754
- radar_collection,
755
- image_formation,
756
- scp_coa,
757
- radiometric,
758
- rma,
759
- )
617
+ sicd_ew["RadarCollection"] = {
618
+ "TxFrequency": {
619
+ "Min": tx_freq_min,
620
+ "Max": tx_freq_max,
621
+ },
622
+ "Waveform": {
623
+ "@size": 1,
624
+ "WFParameters": [
625
+ {
626
+ "@index": 1,
627
+ "TxPulseLength": tx_pulse_length,
628
+ "TxRFBandwidth": tx_rf_bw,
629
+ "TxFreqStart": tx_freq_min,
630
+ "TxFMRate": tx_fm_rate,
631
+ "RcvDemodType": rcv_demod_type,
632
+ "ADCSampleRate": adc_sample_rate,
633
+ "RcvFMRate": 0.0,
634
+ }
635
+ ],
636
+ },
637
+ "TxPolarization": tx_polarization,
638
+ "RcvChannels": {
639
+ "@size": 1,
640
+ "ChanParameters": [
641
+ {
642
+ "@index": 1,
643
+ "TxRcvPolarization": tx_rcv_polarization,
644
+ }
645
+ ],
646
+ },
647
+ }
648
+ now = (
649
+ datetime.datetime.now(datetime.timezone.utc)
650
+ .isoformat(timespec="microseconds")
651
+ .replace("+00:00", "Z")
652
+ )
653
+ sicd_ew["ImageFormation"] = {
654
+ "RcvChanProc": {
655
+ "NumChanProc": 1,
656
+ "ChanIndex": [1],
657
+ },
658
+ "TxRcvPolarizationProc": tx_rcv_polarization_proc,
659
+ "TStartProc": t_start_proc,
660
+ "TEndProc": t_end_proc,
661
+ "TxFrequencyProc": {
662
+ "MinProc": tx_freq_proc[0],
663
+ "MaxProc": tx_freq_proc[1],
664
+ },
665
+ "ImageFormAlgo": image_form_algo,
666
+ "STBeamComp": st_beam_comp,
667
+ "ImageBeamComp": image_beam_comp,
668
+ "AzAutofocus": az_autofocus,
669
+ "RgAutofocus": rg_autofocus,
670
+ "Processing": [
671
+ {
672
+ "Type": f"sarkit-convert {__version__} @ {now}",
673
+ "Applied": True,
674
+ },
675
+ ],
676
+ }
677
+
678
+ sicd_ew["RMA"] = {
679
+ "RMAlgoType": rma_algo_type,
680
+ "ImageType": image_type,
681
+ "INCA": {
682
+ "TimeCAPoly": time_ca_poly,
683
+ "R_CA_SCP": r_ca_scp,
684
+ "FreqZero": freq_zero,
685
+ "DRateSFPoly": dr_sf_poly,
686
+ "DopCentroidPoly": dop_centroid_poly,
687
+ "DopCentroidCOA": dop_centroid_coa,
688
+ },
689
+ }
760
690
 
761
- new_radiometric = _update_radiometric_node(sicd_xml_obj.getroottree())
762
- sicd_xml_obj = sicd.SICD(
763
- collection_info,
764
- image_creation,
765
- image_data,
766
- geo_data,
767
- grid,
768
- timeline,
769
- position,
770
- radar_collection,
771
- image_formation,
772
- scp_coa,
773
- new_radiometric,
774
- rma,
775
- )
691
+ sicd_ew["SCPCOA"] = sksicd.compute_scp_coa(sicd_xml_obj.getroottree())
776
692
 
777
- sicd_xmltree = sicd_xml_obj.getroottree()
693
+ sicd_ew["Radiometric"]["BetaZeroSFPoly"] = beta_zero_sf_poly
694
+ _update_radiometric_node(sicd_ew)
778
695
 
779
696
  # Update ImageCorners
697
+ sicd_xmltree = sicd_xml_obj.getroottree()
780
698
  image_grid_locations = (
781
699
  np.array(
782
700
  [[0, 0], [0, num_cols - 1], [num_rows - 1, num_cols - 1], [num_rows - 1, 0]]
@@ -790,8 +708,7 @@ def hdf5_to_sicd(h5_filename, sicd_filename, classification, ostaid="Unknown"):
790
708
  sarkit.wgs84.up(sarkit.wgs84.cartesian_to_geodetic(scp_ecf)),
791
709
  )
792
710
  icp_llh = sarkit.wgs84.cartesian_to_geodetic(icp_ecef)
793
- xml_helper = sksicd.XmlHelper(sicd_xmltree)
794
- xml_helper.set("./{*}GeoData/{*}ImageCorners", icp_llh[:, :2])
711
+ sicd_ew["GeoData"]["ImageCorners"] = icp_llh[:, :2]
795
712
 
796
713
  # Check for XML consistency
797
714
  sicd_con = SicdConsistency(sicd_xmltree)
@@ -855,21 +772,20 @@ def main(args=None):
855
772
  type=pathlib.Path,
856
773
  help="path of the input HDF5 file",
857
774
  )
858
- parser.add_argument(
859
- "classification",
860
- type=str,
861
- help="content of the /SICD/CollectionInfo/Classification node in the SICD XML",
862
- )
863
775
  parser.add_argument(
864
776
  "output_sicd_file",
865
777
  type=pathlib.Path,
866
778
  help="path of the output SICD file",
867
779
  )
868
780
  parser.add_argument(
869
- "--ostaid",
781
+ "classification",
782
+ type=str,
783
+ help="content of the /SICD/CollectionInfo/Classification node in the SICD XML",
784
+ )
785
+ parser.add_argument(
786
+ "ostaid",
870
787
  type=str,
871
788
  help="content of the originating station ID (OSTAID) field of the NITF header",
872
- default="Unknown",
873
789
  )
874
790
  config = parser.parse_args(args)
875
791