Coder Social home page Coder Social logo

enet4 / dicom-rs Goto Github PK

View Code? Open in Web Editor NEW
394.0 394.0 72.0 5.2 MB

Rust implementation of the DICOM standard

Home Page: https://dicom-rs.github.io

License: Apache License 2.0

Rust 99.99% Shell 0.01%
dicom dicom-standard hacktoberfest medical-imaging rust

dicom-rs's People

Contributors

aaronzs avatar almeida-a avatar bastienvigneron avatar charbeljc avatar dependabot[bot] avatar derorfa avatar dougyau avatar enet4 avatar evanrichter avatar feliwir avatar ibaryshnikov avatar ingwinlu avatar jennydaman avatar jmlaka avatar josepp-moreira avatar lalberge avatar leonz avatar mfreeborn avatar natdash avatar naterichman avatar nicosalvato-medas avatar pauldotknopf avatar pevers avatar pierrebou91 avatar pjsier avatar robyoung avatar vsaase avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dicom-rs's Issues

Can't read unknown Tag

(1001,041e) ST [Date: 20210212025552[^]Date: 20210217033201[^]Date: 20210226002420[^]] # 70, 1 Unknown Tag & Data

Attempting to read in rust fails with:
Error: ParseMetaDataSet { source: UndefinedValueLength { tag: Tag(0x0022, 0x0016), backtrace: Backtrace(()) } }

dcmtk - dcmdump works fine to read the above tag which is where the line came from above.

Easy getter methods for the file meta table

The attributes in the struct dicom_object::meta::FileMetaTable retain the padding from the encoded DICOM file meta group, and so they are usually padded for even length, even when built via the builder. While this makes it easy to serialize, it is not very useful when inspecting the attributes.

This calls for new methods to FileMetaTable which automatically trim the padding character out before returning the string slice.

Example signature (should be one per textual attribute):

fn transfer_syntax(&self) -> &str { unimplemented!() }

Tracker issue for object API ergonomics

Laying out some ideas and issues to keep in mind in order to improve the overall experience with the dicom-object API.

  • Upper-level from_*/write/save functions could be more intuitive.
    • For example, reading from a file expects the file to have a preamble, whereas reading from an arbitrary reader does not (#39).
    • One possible idea is to provide an options builder API which would allow the user to specify certain expectations regarding how the object should be read or written.
    • Object reading ergonomics are already improved in #199
  • Value conversion from retrieved attributes
    • One should have an easy way to convert data in an object's DICOM attributes from a textual format to a binary format and vice versa. This is particularly important for the plans in #9, so that decoding is postponed to the moment where the attribute is needed.
    • Resolved with #56, #65, and #66.
  • DicomObject trait is not sufficiently powerful enough to be usable.
    • It's lacking some useful methods because some of them not generic enough for future implementations.
    • The ideal set of definitions in this trait require generic associated types (GATs).
  • Cannot obtain mutable access to a file object's meta table. Something like a meta_mut() would probably help, but then it would become too easy to provide inconsistent information, unless it is safeguarded with getters and setters. Related with #70.

RLE Support

Hi - I just implemented a DICOM RLE decoder in Rust which you can find here: https://github.com/chafey/dicomrle-rs

I wanted to let you know in case you want to use it for adding support for RLE decoding to this library. I would also appreciate any feedback as I am new to Rust. Thanks!

Using Dicom object

Hello,
This may seem silly issue but i spent hours trying to figure out a way to solve this and i couldn't.

use dicom::core::*;
use dicom::object::*;

fn main() {
    let obj = open_file("01.dcm");
    let patient_name = obj.element_by_name("PatientName").to_str();
    let modality = obj.element_by_name("Modality").to_str();
    let pixel_data_bytes = obj.element(Tag(0x7FE0, 0x0010)).to_bytes();
}

I keep getting an error that element_by_name and element are not found.

Logging foundation

As defined in the roadmap, some situations while working with DICOM data may not be critical to impose a soft error or panic, but should still be called out in some way. Logging comes to play as a non-invasive mechanism to report abnormal situations which do not impede the process, but may bring other issues along the way. As such, it is still relevant to provide this information to developers and to end users of CLI tools.

The two phases for fulfilling this issue would be:

  • Decide on a logging API for all library crates (as a façade to an actual logger implementation which can be decided by dependents). I believe this would be narrowed down to choosing between log, slog, or tracing.
    • tracing it is.
  • Choose a logging implementation for each existing CLI tool (dicom-dump, dicom-scproxy, and so on). One that prints to stdout/stderr would suffice.

Ignore trailing whitespace when retrieving dates/times

A single trailing space of a valid time or date can interfere with the core crate's capability of transforming the DICOM value into a chrono date/time value.

let val = PrimitiveValue::from("170435.45 ");
assert_eq!(val.to_time()?, NaiveTime::from_hms_micro(17, 4, 35, 450_000));

[pixeldata] Integrate with encoding TransferSyntax

This would enable separate crates to install new transfer syntax implementations into end programs.
The way I currently imagine this is:

Image object trait

We need to create a new extension trait for DICOM objects, through which the various implementations can retrieve all the necessary properties, such as the dimensions, photometric interpretation, and the pixel data proper.

Some quick pseudo-Rust to get the idea across:

pub trait PixelDataObject {
    fn rows(&self) -> u16;

    fn columns(&self) -> u16;

    fn samples_per_pixel(&self) -> u16;

    fn bits_allocated(&self) -> u8;

    fn bits_stored(&self) -> u8;

    fn rescale(&self) -> Rescale;

    fn photometric_interpretation(&self) -> PhotometricInterpretation;

    /// Should return either a byte slice/vector if native pixel data
    /// or byte fragments if encapsulated
    fn raw_pixel_data(&self) -> RawPixelData;
}

This trait would be implemented by InMemDicomObject, and perhaps by FileDicomObject<O>.

Change TransferSyntax codec

With the trait above, transfer syntax implementations would then rely on a trait object of said trait to retrieve the image and/or frames of the image.

More details about this will be defined, but for now the short explanation is that Codec could not serve its purpose so well in its current state, and will need to be modified.

use dicom-rs with wasm bindgen

Hey,

I'm trying to use dicom-rs with wasm bindgen for a subassembly app. So far I have something like this function to load a dicom file using JS fetch

pub async fn load_url(url: String) -> Result<(), JsValue> {
    let mut opts = RequestInit::new();
    opts.method("GET");
    opts.mode(RequestMode::Cors);

    let request = Request::new_with_str_and_init(&url, &opts)?;

    let window = web_sys::window().unwrap();
    let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;

    // `resp_value` is a `Response` object.
    assert!(resp_value.is_instance_of::<Response>());
    let resp: Response = resp_value.dyn_into().unwrap();

    // Convert this other `Promise` into a rust `Future`.
    let array_buffer = JsFuture::from(resp.array_buffer()?).await?;

    let typebuf: js_sys::Uint8Array = js_sys::Uint8Array::new(&array_buffer);

    let mut slice = vec![0; typebuf.length() as usize];
    typebuf.copy_to(&mut slice[..]);

    let mut file = Cursor::new(slice);

    let obj = from_reader(&mut file).unwrap();

    // let patient_name = obj.element_by_name("PatientName").unwrap().to_str().unwrap();

    // console::log_1(&patient_name.to_string().into());

    Ok(())
}

Problem is the line let obj = from_reader(&mut file).unwrap() fails with :

image

I'm using the latest master. Not sure if the function I'm calling on the dicom-rs side is the right one. The import is the following: use dicom_object::from_reader;

Colored dcmdump output

It would be interesting to have the project's dcmdump print colored output for better readability and analysis.

This would give tag numbers, attribute names, and respective values, in different colours if the output device is a TTY.

termcolor seems to be the right way to do this.

Default ValueReadStrategy

I am not very experienced with Rust so the issue might be explained easily.

Please explain how to switch from ValueReadStrategy::Preserved to ValueReadStrategy::Interpreted option. My issue is the following: I get a DICOM element of DS type however the element holds PrimitiveValue::Strs instead of PrimitiveValue::F64 because of using decode::read_value_preserved rather than decode::read_value inside the library based on what I have studied in the code.

My sample code is following:

fn print_value<I, P>(value: &DicomValue<I, P>) -> &str {
    if let Ok(_) = value.string() {
        return "string";
    }
    if let Ok(_) = value.uint16() {
        return "uint16";
    }
    if let Ok(_) = value.float64() {
        return "float64";
    }
    return "unknown"
}

I call print_value for each DataElement of a file. Almost any 16-bit image file contains the Window Center/Window Width tags which are float-point values. However, my code never returns float64.

Improve file information table consistency guarantees

The abstraction FileMetaTable, which contains the processed properties of a DICOM file's meta information group, is defined as a plain data struct. It is easy for a user to construct a table in such a way that always results in a corrupted DICOM file. And once modifying the attributes of an existing this file meta group becomes a feature of the crate, better facilities should be provided to ensure that the file remains consistent.

This issue serves to:

  • Evaluate measures of consistency to be applied to the FileMetaTable, or another type which would take the same responsibilities.
    • Should all modifications be guarded by setters so that the group length is automatically updated? Or should receivers of a file meta object validate the given length and recalculate it only if necessary?
    • The current status is that the methods into_element_iter and write do not validate the length, but perhaps they should.
  • Propose &mut self methods for setting and clearing file meta information properties while doing the necessary adjustments.
  • Also propose &self methods for retrieving clean values of these properties

Add .into_text_value() for core DICOM values

Many important DICOM attributes rely on a textual value representation even if their intent is to encode numbers (in emphasis, DS and IS). On the other hand, it might be easier for some users to collect numbers in binary form and create a DICOM value directly from them.

The idea is the following: provide the method into_text_value(self) that consumes the value (PrimitiveValue and Value<I, P>) and returns a value (Self) which is always represented as text, performing a conversion if necessary.

let instance_number = dicom_value!(U16, [10]);
let instance_number_text = instance_number.into_text_value();
assert_eq!(instance_number_text, dicom_value!(Strs, ["10"]));

WebAssembly support

Is it a goal or non-goal?
It worked out of the box before 0.1, but not supported by inventory yet.

Question about PixelData transformations

After reading PixelData there may be a number of transformations which should be applied to individual pixels like RescaleSlope / RescaleIntercept / WindowCenter / WIndowWidth / and may be more.
Is there a rust crate or other convenient tool for correct transformations of pixels after reading them?

Error while trying to parse valid dicom file

Hi,

I have this valid dicom file. i tried to run the simple program in the readme but i receive the following error:

Error: ReadValue(ParseFloat(ParseFloatError { kind: Invalid }))

at the line

let obj = open_file("949559.dcm")?;

What can it be?

Lazy loading of Multi-frame files

Hi @Enet4! Thank you for creating such an awesome library!

I have a specific use case: loading big .dcm files (over 500Mb) in browser. At the moment most of the browsers have a limit for webassembly memory of about 2Gb, and when I run my program, it usually crashes with out of memory error.

Is there a way we can collaborate to support lazy loading?
In particular, I need to iterate over the PixelData items in Multi-frame file

Writing data sets with encapsulated pixel data may have an unintuitive behavior

The current data set writing capabilities via the object write_dataset methods allow the user to choose the transfer syntax of the output data:

let ts = TransferSyntaxRegistry.get("1.2.840.10008.1.2.1").unwrap();

obj.write_dataset_with_ts(&mut out, &ts)?;

However, the methods do not check whether the object's pixel data encoding matches the requested output transfer syntax. It merely passes over the pixel data as is, either as native encoded pixel data or as a sequence of fragments. They were designed this way so that this implementation does not have to check the pixel data and other properties to identify how it was encoded. However:

  1. There may be interest in converting from one pixel data encoding to another in an almost seamless fashion.
  2. It may be surprising to read a DICOM object from a file and then write the data set to a channel as part of a networking service, and realize that no pixel data conversion was done, leading to an inconsistent object at the destination.

This might only be tackled when the image abstraction becomes available, but it's worth recording this concern for now.

Best-effort resolution of transfer syntax of DICOM files without file meta group

The current file reading implementation requires DICOM files to have a file meta group. The only way to open it would be by specifying the expected transfer syntax (introduced in #84). Although to the best of my knowledge the lack of this group is non-standard, it is known that some implementations are capable of resolving this anyway.

  • Make file opening more flexible by continuing the process even without finding enough elements for a compliant file meta group table, by assuming a flexible transfer syntax.
    • As a best effort, this is something that can be reiterated as we stumble upon more files to test with, but it should go along something like trying Explicit VR Little Endian first, then Implicit VR Little Endian if the outcome of the former did not make sense.
  • Leave a warning (see #49) in the case that the file meta group is missing.

One could start by writing tests for the test files in dicom-test-files without a file meta group (see example in #48), then working your way into making them pass.

Refactor documentation to use intra-doc links

Intra-doc links are already stabilized, have worked in docs.rs for far longer than that, and are easier to write and less error prone than working with HTML links directly. I believe it is time for DICOM-rs to embrace them.

I would be interested in replacing existing links with intra-doc links where applicable.

Tracker issue for standard data dictionaries

Let this issue be used to keep track of how the project is currently encoding and providing data dictionaries, as specified in DICOM PS3.6 - Data Dictionary.

  • File Meta group attributes
    • Available, manually introduced
  • Command elements
    • Defined in PS3.7 chapter E
    • Available just like any other standard data element, via #8
  • Data element / Attributes (tags to name plus info such as VR and VM)
    • API in dicom-core
    • Currently provided at run-time by the dicom-dictionary-std crate.
    • Code constants to Tag instances
  • Transfer Syntax unique identifiers
    • Registry in transfer-syntax-registry
    • Can retrieve implementation status and TS name by UID
    • See if this can be easily integrated with dcmdump, so as to present the alias instead of the UID (resolved in #61)
  • SOP Class dictionary
  • Directory Structuring Elements
    • Not implemented, should probably be done alongside an implementation of DICOMDIR.
  • Other unique identifiers: Context Group values, LDAP OID, Frames of Reference, Coding Schemes, ...
    • Only implemented as UID constants
  • Dynamic RTP Payload Elements
    • Not implemented, very specific to RTP payloads
  • Color palettes
    • Not implemented, not worth thinking about before writing the pixel data abstraction (see #31).

Issues with too early dates?

I started playing with this library, as I used Rust in my previous job and now I have to work with DICOM. As I tried the dcmdump tool on one of my files, I unfortunately ended up with an error:

Error: ReadValue(DateTimeZone)

I looked at the source code but I could not really figure out where this error comes from. However when I looked at my DICOM file with dcmtk/dcmdump I saw the following:

(0008,0020) DA [19620728]                               #   8, 1 StudyDate
(0008,0021) DA [19000101]                               #   8, 1 SeriesDate
(0008,0022) DA [19620728]                               #   8, 1 AcquisitionDate
(0008,0023) DA [19620728]                               #   8, 1 ContentDate
(0008,0030) TM [000000.000000]                          #  14, 1 StudyTime

As you see those dates are before the UNIX epoch. I am not sure if this has anything to do with the error I encountered, but it could be (I don't think these dates are real, these files have been through some anonymization processes, probably multiple times).

I am happy to help debugging the issue, unfortunately I cannot send you any DICOM files, so I can only help executing stuff on your behalf :)

Writing DICOM files?

I've been working on SCU/SCP support. I've had to pause because of the missing write support.

With that said, what are you thinking with regards to writing? Do you want to stub out some traits and then I will handle the implementation/tests?

Retrieve date/time range from textual element value

In the context of queries, data elements with the value representations DA, TM, or DT can have two time instances separated by a dash (standard). While no decoded value variant is available for ranges, they can be retrieved from string variants.

I picture being able to do the following:

let val = dicom_value!(Str, "20200313-20200930");
let (start, end) = val.date_range()?;
assert_eq!(start, NaiveDate::from_ymd(2020, 3, 13));
assert_eq!(end, NaiveDate::from_ymd(2020, 9, 30));

Parse Specific Charset error.

Hi!
I've added support for Chinese encoding, but Chinese characters still can't be parsed correctly. At last I found the reason why it went wrong.
The Character set should be changed here, but it never seems to run here. Because the Specific Character code is CS, not UI. Please take a look here.

Tracker issue for text encoding

Keeping a table and checklist of requirements regarding text encoding in DICOM:

encoding implemented validated Issue / PR
ISO IR 100 (West Europe) ✔️ baseline only #53
ISO IR 101 (Central/East Europe) ✔️ baseline only #53
ISO IR 109 (South Europe) ✔️ baseline only #53
ISO IR 110 (North Europe) ✔️ baseline only #53
ISO IR 144 (Cyrillic) ✔️ baseline only #53
ISO IR 192 (UTF-8) ✔️ baseline only
GB18030 (Simplified Chinese) ✔️ baseline only #51 #52
ISO IR 13 (Japanese Katakana)
ISO IR 87 (Japanese Kanji/Hiragana/Katakana)

In addition:

  • Validate edge cases in the the default character encoding
  • Validate the handling of unsupported character sets
  • Decoding/encoding of ideographic and phonetic person names
  • #443
  • #200
  • #278

Improve error definitions

Although error types are already statically delimited, errors emerging from the library currently contain little to no context about where they happened. This is an example of an error value which may emerge when opening a file: DataSetSyntax(PrematureEnd)

Requesting a backtrace is not useful because the error was raised with the ? operator, without keeping the full backtrace from the origin of the error at the library level. quick-error has been originally employed as a means to easily create error types, but for a solution of this scale, it becomes harder to work with and does not contribute to good errors.

As declared in the roadmap, it is of my interest to change the existing error definitions to something more informative and organized. I will try to rewrite existing errors with the use of another crate (likely either snafu or thiserror), which will provide the much needed quality of these error values.

Using dicom_object::open_file

Hello, thank you for providing DICOM support for Rust.

I was trying to run a minimal example using this data.

ftp://medical.nema.org/medical/dicom/DataSets/WG16/Siemens/Siemens_spectroEnhDICOM/

use dicom_object::open_file;
use dicom_object::Result;

let file_path = "Anonymous.MR._.12.1.2017.06.28.09.41.02.294.59320505.dcm";
let obj = open_file(file_path);
let is_ok = obj.is_ok();
println!("is ok {}", is_ok);

Always print false. I tried with other datasets too.
My rustc version:

rustc --version
rustc 1.38.0 (625451e37 2019-09-23)

How can I make it work?

Thanks.

Interpreting string-based values?

I have a question about some concerns I have about pre-interpreting data of certain VR types.

For example, the VR::IS is being interpreted as an [i32] internally.

Because of this, if we were to load a dicom file, and save it without making any modifications, the saved file would be normalized, in that the VR::IS would be converted into an array of integers, and then back to a string.

This would also pose a problem with implementing validation checkers. I'd like to develop a command line tool that loads a DICOM file, and validates it's contents. I can't validate any field at all if any one field prevents me from loading the entire DICOM file.

IMO, it is important to keep values that are represented with the Default Character Repertoire as characters. We could provide utilities to re-interpret the values into their typed representation (date times, date ranges, integer strings, etc) after the DICOM file is loaded.

Getters for element value text without padding

In the core crate, retrieving a string or sequence of strings from a value may yield unwanted padding whitespace, usually added to keep values with an even length.

While at this time I am not interested in automatically stripping the whitespace out, it would be nice to have some getter methods which provide a "clean" version of the string.

let value = PrimitiveValue::from("1.2.345\0".to_string());
assert_eq!(&value.to_clean_str(), "1.2.345");

let value = dicom_value!(Strs, ["ONE", "TWO", "THREE", "SIX "]);
assert_eq!(&value.to_clean_str(), "ONE\\TWO\\THREE\\SIX");

How to retrieve pixel data

Apologies for the likely naive question, but is there a way to retrieve the PixelData from a DICOM, such that it could be opened with the image crate or something similar?

Thanks!

Using DCMTK for the standard dictionary

Take a look at dicom.dic.

It is carefully curated by the DCMTK team, in coordination with the authors of the DICOM standard. It is also updated routinely with supplements (take a look at git history).

I recommend updating the dictionary build to use it, instead of the xml version of the DICOM standard. You wouldn't need the separate/static list of "META" entries. This change would also invalidate this PR.

Add take_element methods for InMemoryDicomObject

Allow the user of dicom_object to take the element from the object, removing it in the process.

For in-memory objects, this can translate to less data copying.

    /// <document please>
    pub fn take_element(&mut self, tag: Tag) -> Result<InMemElement<D>> {
        todo!()
    }

    /// <document please>
    pub fn take_element_by_name(&mut self, name: &str) -> Result<InMemElement<D>> {
        let tag = self.lookup_name(name)?;
        self.take_element(tag)
    }

Helping out with pixel data decoding

Hi @Enet4 !

Thanks for this awesome library!

I'm now using this library to generate thumbnails for a bunch of JPEG lossless compressed dicoms that I have. I created a simple abstraction here: https://github.com/pevers/dicom-pixel-data, using GDCM bindings to decode pixel data into a DynamicImage:

Example from the tests:

let obj = open_file(dicom_test_files::path(value).unwrap()).unwrap();
let image = obj.decode_pixel_data().unwrap().to_dynamic_image().unwrap();
image
    .save(format!(
        "out.png",
    ))
    .unwrap();

Not everything is supported yet, but it can at least decode a bunch of example lossless JPEG dicoms from the Pydicom test set. I created a thin GDCM wrapper because I don't think there is solid support for the wide variety of dicom compression formats in Rust.

My question: I read on roadmap that this is a requested feature. Can I help by creating a PR to this repo? Or is this already in the making? I'm fairly new to Rust so I guess it would require some extensive reviewing but I would be glad to help out a bit.

Thanks again for your work!

Cheers

Handling empty date

Sometimes the date in DICOM file is 0000-00-00. Is it a common case in the ecosystem when the date is empty?

How to implement additional transfer syntaxes?

Hi @Enet4 ! I'd like to implement additional transfer syntax in my local fork, in particular
JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]) 1.2.840.10008.1.2.4.70
Can you give any advice about doint it? Even link to a good doc would be helpful, because at the moment I'm stuck with the question how do transfer syntaxes work together, for example is any of the JPEG transfer syntaxes a big endian or little endian?
I also would be happy to share these changes once you are ready to accept PRs

Distinguish null components in date/time values

As per the standard, part 5, section 6.2:

A component that is omitted from the string is termed a null component. Trailing null components of Date Time indicate that the value is not precise to the precision of those components. The YYYY component shall not be null. Non-trailing null components are prohibited. The optional suffix is not considered as a component.

As the variants of a PrimitiveValue currently decode date and time values into chrono date/time types, we no longer hold the information of which components were null once decoded from their textual form. The null components are reverted to the "first" values when decoding a date with these: january, day 1, 0 hours, 0 minutes, etc.

Since textual representations are already preserved default (this is done in #9), the DICOM parser will choose to keep DA, TM, and DT as plain text, and thus no information will be lost. Still, it is best to also have some way to store these values in a binary format, one that retains information about null components while still enabling an intuitive conversion to a standard date/time type for subsequent manipulation.


One acceptable way of resolving this would be:

  • New types (maybe PartialDate) with multiple variants depending on how many components are defined. They might best be implemented as enums, and would have to have several utility methods in order to be usable.
  • New methods .to_partial_date, .to_partial_time, .to_partial_datetime on DICOM value types.

Write object to arbitrary writer

dicom_object is missing methods for writing the object's data set to arbitrary data writers.

This is a requirement for connecting this API with the upper layer protocol, in order to create DICOM network services.

How to work with SQ tags

Sorry for this stupid question but I tried to do my best for a few hours... better to ask here. Perhaps, this is a problem of my bad skills with Rust.

I have a DicomValue<I, P> object with SQ tags. I call items to further iterating thru [I] However, I is a simple EmptyObject structure by default so I have no idea how to retrieve the sequence items.

Can you share a sample code of working with SQ tags?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.